如何将行转换为列并在Mysql

时间:2015-05-13 11:40:14

标签: mysql sql

我有三个表患者表:其中包含我的患者姓名,控件表:表示可以为每种疾病绘制的UI控件,< strong> ControlsValues 表,其中包含为每位患者提交的控件的值

让我们有一些数据患者

|ID  | Name |
|-----------|
| 1  | Ara  |
| 2  | Sada |

控件

|ID  | Text | Type     |
|-----------|----------|
| 1  | age  | textbox  |
| 2  |alergy| checkbox |

然后是controlsValues表,这是我想在

查询的地方
|ID  | contrlId | value    | patientId |
|---------------|----------|-----------|
| 1  | 1        | 23       | 1         |
| 2  | 2        | true     | 1         |
| 3  | 1        | 26       | 2         |
| 4  | 2        | false    | 2         |

这里我的问题出现在我想从ControlsValues表中返回那个患有(controlId=1 AND value=23) and (controlId=2 AND value=true)的患者,在这种情况下条件是两行而不是两列,这是不可能的,所以我决定更改行根据controlId进入列,但我不知道如何和我一直在寻找2天并看到了很多样本​​,但没有一个帮助我解决我的问题

5 个答案:

答案 0 :(得分:2)

尝试这个

    select * from controlvalues;

    +----+----------+-------+-----------+
    | id | contrlId | value | patientId |
    +----+----------+-------+-----------+
    |  1 |        1 | 23    |         1 |
    |  2 |        2 | true  |         1 |
    |  3 |        1 | 26    |         2 |
    |  4 |        2 | false |         2 |
    |  5 |        1 | 23    |         3 |
    |  6 |        2 | true  |         3 |
    +----+----------+-------+-----------+
    6 rows in set (0.00 sec)

    MySQL的&GT; SELECT cv1.patientId p1,cv1.contrlId ctrl1,cv1.value val1,cv2.patientId p2,cv2.contrlId ctrl2,cv2.value val2     FROM controlvalues cv1,controlvalues cv2     WHERE cv1.patientId = cv2.patientId和cv1.contrlId = 2和cv1.value ='true'和cv2.contrlId = 1和cv2.value ='23';

+------+-------+------+------+-------+------+
| p1   | ctrl1 | val1 | p2   | ctrl2 | val2 |
+------+-------+------+------+-------+------+
|    1 |     2 | true |    1 |     1 | 23   |
|    3 |     2 | true |    3 |     1 | 23   |
+------+-------+------+------+-------+------+
2 rows in set (0.00 sec)

答案 1 :(得分:1)

考虑以下内容(我现在暂时忽略其他表):

CREATE TABLE pcv
(patient_id INT NOT NULL
,control_id INT NOT NULL
,value    VARCHAR(12) NOT NULL
,PRIMARY KEY(patient_id,control_id)
);

INSERT INTO pcv VALUES
(1,1,'23'),
(1,2,'true'), 
(2,1,'26'),
(2,2,'false');

SELECT * FROM pcv;
+------------+------------+-------+
| patient_id | control_id | value |
+------------+------------+-------+
|          1 |          1 | 23    |
|          1 |          2 | true  |
|          2 |          1 | 26    |
|          2 |          2 | false |
+------------+------------+-------+

有两种标准解决方案。第一个是慢写但更简单:

解决方案1:

SELECT patient_id
     , MAX(CASE WHEN control_id = 1 THEN value END) age
     , MAX(CASE WHEN control_id = 2 THEN value END) allergy
  FROM pcv
 GROUP
    BY patient_id;
+------------+------+---------+
| patient_id | age  | allergy |
+------------+------+---------+
|          1 | 23   | true    |
|          2 | 26   | false   |
+------------+------+---------+

解决方案2:

SELECT pcv1.patient_id
     , pcv1.value age
     , pcv2.value allergy 
  FROM pcv pcv1 
  LEFT 
  JOIN pcv pcv2 
    ON pcv2.patient_id = pcv1.patient_id 
   AND pcv2.control_id = 2 
 WHERE pcv1.control_id = 1;
+------------+-----+---------+
| patient_id | age | allergy |
+------------+-----+---------+
|          1 | 23  | true    |
|          2 | 26  | false   |
+------------+-----+---------+

请注意,采用EAV模型时,尽可能使用适当的数据类型仍然是一种很好的做法。因此,您可能有一个存储日期信息的表,另一个存储字符串信息。

答案 2 :(得分:1)

另一种方法是计算匹配的行数,如果你需要确保它们满足超过你设定的标准数量 - 毕竟,你可能有多个匹配!如果你想变得复杂,设置一个变量,它具有匹配的最小记录数,并从那里开始。

SELECT  P.ID, P.Name, COUNT(*)
FROM    Patients    P
JOIN    ControlsValues  V ON V.patientId = P.ID
WHERE   (V.value = 23 AND V.ControlId = 1)
OR  (V.value = 'true' AND V.ControlId = 2)
GROUP BY P.ID, P.Name
HAVING COUNT(*) > 1

答案 3 :(得分:1)

您可以通过加入将行表示为列。

select
    *
from controlsValues cv1
join controlsValues cv2
    on cv1.patientId = cv2.patientId
    and cv1.id <> cv2.id -- remove duplicates
where
    cv1.contrlId = 1 AND cv1.value = 23
    and cv2.contrlId = 2 AND cv2.value = 'true'
;

现在您可以看到23岁并且患有过敏症的患者。

答案 4 :(得分:-1)

解决问题的方法是使用子查询

select patientId from controlValues 
where controlId=1 AND value=23 
and patientId in (
    select patientId 
    from controlValues 
    where controlId=2 and value=true
)