【问题标题】:Crosstab function for table is not carrying the values along表的交叉表函数没有携带值
【发布时间】:2017-08-09 15:56:11
【问题描述】:

我当前的 sae_table(id, cbid, description, value) 和图片一样。

我想旋转它,所以它看起来像这样:

id     cbid    month    day   year    test   actual_value   normal_ran   no
1    60051     09       27    2016  "Urinary" "some vegetans"
2    60051     09       30    2016  "Chest"   
3    60052  ....

我尝试使用 id、description 和 value 进行交叉表,但所有值仅显示在 Month 列下。

SELECT * FROM CROSSTAB('SELECT id, description,value from sae_test')
 AS ct ("id" integer,  "Month" character varying(4000),"Day" character varying(4000),"Year" character varying (4000),
 "Test" character varying(4000),"Actual Value" character varying(4000),"Normal Range" character varying(4000),"No Test option" character varying(4000));

交叉表结果上方(值未正确分布在列中):

id    Month    Day   Year     ...
1      09                     ...
2      27                     ...
3      2016                   ...

我还尝试仅使用 cbid、描述和值进行旋转。但它只显示独特的 cbid。在这种情况下,一个 cbid 可以有多行。

SELECT * FROM CROSSTAB('SELECT * from sae_rel_data2()')
 AS ct ("CBID" character varying(4000), "Month" character varying(4000),"Day" character varying(4000),"Year" character varying (4000),
 "Test" character varying(4000),"Actual Value" character varying(4000),"Normal Range" character varying(4000),"No Test" character varying(4000));

上述查询的结果是(消除了相同 cbid 的第二个条目,而这些条目应该保留):

cbid    month   day    year   ...
60051    09     27     2016   ...
60052                         ...
60053    09     27     2016   ...
60029                         ...

更新:

如果我有有助于识别 CBID 的第 n 条记录的序号怎么办?然后我可以创建一个循环函数,为每个序数级别的 cbid 执行交叉表,然后将每个与 UNION 或 JOIN 语句结合起来吗?那行得通吗?如果是这样,如何创建该循环?我不熟悉。

例子:

event_crf_id;        description,            value,        ordinal
444;                 "CBID";                "60051";          1
444;                 "Month";               "09";             1
444;                  "Day";                "27";             1
444;                  "Year";               "2016";           1
444;                  "Test";         "Urinary tract US";     1
444;               "Actual Value";   "some vegetans lesions"; 1
444;                 "Normal Range";         "";              1
444;               "No tests option";        "";              1
444;                 "Month";                "09";            2
444;                 "Day";                  "30";            2
444;                 "Year";                "2016";           2
444;                 "Test";             "Chest/abdomen CT";  2
444;             "Actual Value";         "3 bladder lesions"; 2
444;              "Normal Range";              "";            2
444;             "No tests option";            "";            2

类似:

count=count (distinct ordinal) from sae_test()
for each event_crf_id in (select * from sae_test() where ordinal=count)
   SELECT * FROM CROSSTAB('SELECT event_crf_id, description, value from sae_test()) 
 JOIN ...
count=count+1

有这种可能吗?如何执行此连接?还是 postgres 自动知道在循环中新条目将继续添加到表中? (抱歉,总的来说,我对 Postgres 和数据库很陌生)

【问题讨论】:

  • 您的数据不明确。应该为行60051 和列Day 提供什么值?应该是27 还是30? (顺便说一句,以文本形式提供您的数据,而不是图像)。
  • 应该有一个唯一的值来确定哪个日期或测试或“实际值”是 2. 3. 或 nth 60051 的一部分?第二个问题:如果这些值以未排序的方式插入,您如何分隔每个 60051 行组?
  • 这样想,数字 60051 代表一个病人,那个病人可以在不同的日期有多个实验室。这就是为什么您会反复看到 60051。所以一个 cbid 可以有多个条目,但每个条目都有一个唯一的 id。但是为什么当我执行 SELECT * FROM CROSSTAB('SELECT id, description,value from sae_test') 时,所有数据都显示在第二列下?
  • 因为交叉表第一列需要具有相同唯一值的行。你的 id 是一个连续的数字,所以它不能被排序。但是如果你使用 cbid,它也会消除它的第二个第三个 nth 条目,因为他不知道哪个日期或其他列是 nth cbid 的一部分。
  • 如果您想从每月 27 日开始获取患者 60051 的行,您的查询看起来如何?

标签: postgresql pivot-table crosstab


【解决方案1】:

我确实不得不以艰难、不成熟的方式来做这件事。但它确实为我提供了我想要的结果。我怎样才能以更复杂、更有效的方式做到这一点?

Select a.event_crf_id, rel_test_CBID, a.row_number, a.rel_test_name, rel_test_actual_value, rel_test_month, rel_test_day, rel_test_year, rel_test_normal_range From (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_name
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and i.description = 'Test') as a

left join (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_actual_value
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and i.description = 'Actual Value') as b
on a.event_crf_id = b.event_crf_id and a.row_number = b.row_number

left join (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_month
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and i.description = 'Month') as c
on a.event_crf_id = c.event_crf_id and a.row_number = c.row_number

left join (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_day
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and i.description = 'Day') as d
on a.event_crf_id = d.event_crf_id and a.row_number = d.row_number

left join (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_year
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and i.description = 'Year') as e
on a.event_crf_id = e.event_crf_id and a.row_number = e.row_number

left join (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_normal_range
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and i.description = 'Normal Range') as f
on a.event_crf_id = f.event_crf_id and a.row_number = f.row_number

left join (Select id.event_crf_id, id.ordinal as row_number, id.value as rel_test_CBID
from item i, item_data id 
where i.item_id=id.item_ID and id.item_id IN (2185,2262,2263,2264,2265,2266,2267,2268) and id.ordinal = 1 and i.description = 'CBID') as g
on a.event_crf_id = g.event_crf_id

order by a.event_crf_id, a.row_number asc;

【讨论】:

  • 将您的示例数据hier 与两个表中的insert into from your_table 放在一起。
猜你喜欢
  • 1970-01-01
  • 2011-11-27
  • 2020-05-24
  • 2021-07-23
  • 2013-09-16
  • 2016-01-11
  • 2019-05-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多