MySQL查询 - 选择2行,具有2个特定的DISTINCT列值

时间:2016-04-29 21:40:39

标签: python mysql sql mysql-connector-python

我的目标是,为每个PID选择2条test_sname值为' 想要'和' 想要2 '发生在同一entry_date上。我为包含entry_dates的前5个test_snames执行此操作。

这是我完成此任务的查询:

queryBuilder = 
"""select PID, test_sname, test_value, units, ref_range, entry_date from labs
   where PID=%s and (test_sname='want' or test_sname='want2') and entry_date in

   (select entry_date from labs where PID=%s and test_sname in ('want', 'want2')
   group by entry_date having count(*) = 2) 

   order by entry_date limit 10;""" % (pid, pid)

当entry_date只有两行包含test_sname' 想要'或' want2 '。

PID      |test_sname  |test_value  |units    |entry_date
10000000 | want       |         343 | U/L     | 2008-01-01 01:01:01
10000000 | want2      |      984.34 |         | 2008-01-01 01:01:01
10000000 | NA1        |          56 | %       | 2008-01-01 01:01:01
10000000 | NA2        |         420 | mg/dL   | 2008-01-01 01:01:01
10000000 | NA2        |         420 | mg/dL   | 2008-01-02 01:01:01

10000000 | want       |         343 | U/L     | 2008-01-02 01:01:01
10000000 | want2      |      984.34 |         | 2008-01-02 01:01:01
10000000 | NA1        |          26 | %       | 2008-01-02 01:01:01
10000000 | NA2        |         410 | mg/dL   | 2008-01-02 01:01:01
10000000 | NA2        |         455 | mg/dL   | 2008-01-02 01:01:01

查询结果(正确):

PID      |test_sname  |test_value  |units    |entry_date
10000000 | want       |         343 | U/L     | 2008-01-01 01:01:01
10000000 | want2      |      984.34 |         | 2008-01-01 01:01:01
10000000 | want       |         343 | U/L     | 2008-01-02 01:01:01
10000000 | want2      |      984.34 |         | 2008-01-02 01:01:01

问题来自,例如,test_sname 想要'在同一个entry_date上,因为having count(*) = 2不再有效。这样的数据没有结果。

PID      |test_sname  |test_value  |units    |entry_date
11111111 | want       |         343 | U/L     | 2009-10-26 07:25:00
11111111 | want2      |      984.34 |         | 2009-10-26 07:25:00
11111111 | want       |        189 | U/L     | 2009-10-26 07:25:00
11111111 | NA1        |         50 | %       | 2009-10-26 07:25:00
11111111 | NA2        |         40 | mg/dL   | 2009-10-26 07:25:00
11111111 | NA3        |      84.55 |         | 2009-10-26 07:25:00
11111111 | NA4        |        4.5 | thou/uL | 2009-10-26 07:25:00
11111111 | NA5        |       14.6 | g/dL    | 2009-10-26 07:25:00
11111111 | NA6        |       0.96 | mg/dL   | 2009-10-26 07:25:00

11111111 | want       |         343 | U/L     | 2009-10-30 07:25:00
11111111 | want2      |      984.34 |         | 2009-10-30 07:25:00
11111111 | want       |        189 | U/L     | 2009-10-30 07:25:00
11111111 | NA1        |          6 | %       | 2009-10-30 07:25:00
11111111 | NA2        |         40 | mg/dL   | 2009-10-30 07:25:00
11111111 | NA3        |      84.55 |         | 2009-10-30 07:25:00
11111111 | NA4        |        4.5 | thou/uL | 2009-10-30 07:25:00
11111111 | NA5        |       14.6 | g/dL    | 2009-10-30 07:25:00
11111111 | NA6        |       0.96 | mg/dL   | 2009-10-30 07:25:00

作为限制,我尝试在子查询中放置一个limit 2(我知道这本身就不能解决问题),但它给出了这个错误,我认为我有最新的SQL版本,显然我不能在子查询中使用limit

This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

我意识到有多种方法可以解决这个问题 - 我可以选择所有值,然后以编程方式获取我需要的Python,但我正在寻找使用Python mySQL-connector编写的mySQL查询解决方案。我不会抱怨python解决方案。

我正在使用python v3.4.4和mySQL-connector v2.1.3以及MySQL服务器v5.7.11

谢谢你的时间!

1 个答案:

答案 0 :(得分:1)

考虑通过子查询使用分组的运行计数。然后,在RowNo为1或2的任何位置进行过滤。这样,您将不需要传递参数,因为将处理所有PID。以下假设labs表具有唯一标识符ID

SELECT * 
FROM
   (SELECT PID, test_sname, test_value, units, ref_range, entry_date,    
           (SELECT count(*) FROM labs sub
            WHERE sub.test_sname in ('want', 'want2')
            AND sub.PID = labs.PID
            AND sub.entry_date = labs.entry_date
            AND sub.ID <= labs.ID) As RowNo
    FROM labs
    WHERE test_sname in ('want', 'want2')
   ) As dT
WHERE dT.RowNo <= 2

#  PID     test_sname   test_value      units   ref_range              entry_date   RowNo
#  10000000      want           33        U/L        4-40     2008-01-01 01:01:01       1
#  10000000     want2        98.34                            2008-01-01 01:01:01       2
#  10000000      want           33        U/L        4-40     2008-01-02 01:01:01       1
#  10000000     want2        98.34                            2008-01-02 01:01:01       2
#  11111111      want           33        U/L      Apr-40     2009-10-26 07:25:00       1
#  11111111     want2        98.34                            2009-10-26 07:25:00       2
#  11111111      want           33        U/L      Apr-40     2009-10-30 07:25:00       1
#  11111111     want2        98.34                            2009-10-30 07:25:00       2