SQL组通过从分组中排除NULL值

时间:2015-11-03 06:03:48

标签: mysql sql group-by

我在表中有这种情况

client   staff   code   time1   time2
------------------------
c1       null    code1
c2       null    code1
null     s1      code1
null     s2      code1

尝试按员工和代码对行进行分组:

SELECT GROUP_CONCAT(client),staff,code from table GROUP BY staff,code

我明显得到了:

client   staff   code   ...  time1   time2
------------------------
c1,c2    null    code1
null     s1      code1   <-
null     s2      code1   <-

出于要求的功能的目的,我需要在工作人员“聚焦”条目,所以我也可以获得相对时间1和时间2。 问题是上面箭头指示的行没有任何客户端ID,因此没有机会检索他们的数据。 客户信息进入staff = null行。

我怎样才能达到这样的目标?

client   staff   code   ...  time1   time2
------------------------
c1,c2    s1      code1   <-
c1,c2    s2      code1   <-

感谢

3 个答案:

答案 0 :(得分:0)

(答案不多:),但可能会对其他人有所帮助!)

首先,您必须认识到单个FROM不能同时使用 b c1和s1生成一行,而另一行同时使用 both > c1和s2。当然,除了带有GROUP_CONCAT(client), GROUP_CONCAT(staff)的单行之外,但这没有用,因为它失去了客户与员工之间的联系。

您要做的就是将表与自身连接起来:

client   staff   code   
------------------------
c1       null    code1
c2       null    code1
null     s1      code1
null     s2      code1
c3       null    code1*
c4       null    code2*


SELECT c.client, s.staff, c.code
FROM `table` c
INNER JOIN `table` s ON s.code = c.code

client   staff   code
------------------------
c1       null    code1
c1       null    code1
c1       s1      code1
c1       s2      code1

c2       null    code1
c2       null    code1
c2       s1      code1
c2       s2      code1

null     null    code1
null     null    code1
null     s1      code1
null     s2      code1

null     null    code1
null     null    code1
null     s1      code1
null     s2      code1

很显然,两个4行表之间的交叉连接得到16个结果。排除具有null的行:

SELECT c.client, s.staff, c.code
FROM `table` c
INNER JOIN `table` s ON s.code = c.code AND s.staff IS NOT NULL
WHERE c.client IS NOT NULL

client   staff   code
------------------------
c1       s1      code1
c1       s2      code1

c2       s1      code1
c2       s2      code1

然后,您可以按人员和代码分组,并汇总客户:

SELECT GROUP_CONCAT(c.client), s.staff, c.code
FROM `table` c
INNER JOIN `table` s ON s.code = c.code AND s.staff IS NOT NULL
WHERE c.client IS NOT NULL
GROUP BY staff, c.code

client   staff   code
------------------------
c1,c2     s1      code1
c1,c2     s2      code1

NB:按照书面规定,不会显示仅包含客户而非员工的代码,以及仅包含员工而非代码的代码。如果可能出现这种情况,那么您必须LEFT JOIN所关注的表(table c LEFT JOIN staff stable s LEFT JOIN table c,对NULL进行适当的测试),而不是INNER JOIN。

client   staff   code   time1   time2
------------------------
c1       null    code1
c2       null    code1
null     s1      code1
null     s2      code1
*c3      null    code2*
*null    s3      code3*

SELECT GROUP_CONCAT(c.client), s.staff, c.code
FROM `table` c
LEFT JOIN `table` s ON s.code = c.code AND s.staff IS NOT NULL
WHERE c.client IS NOT NULL
GROUP BY staff, c.code

client   staff   code
------------------------
c1,c2     s1      code1
c1,c2     s2      code1
c3        NULL    code2

SELECT GROUP_CONCAT(c.client), s.staff, c.code
FROM `table` s
LEFT JOIN `table` c ON c.code = s.code AND c.client IS NOT NULL
WHERE s.staff IS NOT NULL
GROUP BY staff, c.code

client   staff   code
------------------------
c1,c2     s1      code1
c1,c2     s2      code1
NULL      s3      code3

目前尚不清楚为什么您的行中的客户或工作人员都已填补(但不能同时填写);也许您应该重新考虑您的模型。

答案 1 :(得分:0)

使用SELECT *并确定您的共同唯一行。在我的示例中,我想要个人资料。有些人可能没有消息,有些人可能没有身份验证。因此,不是在身份验证上使用GROUP BY或在用户名上使用GROUP BY的消息,所有行 都会有此数据返回,即使添加了GROUP BY和行之后包含NULL的列将返回 still

问题中发布的代码返回任何唯一行,因此注释了GROUP BY子句并使用SELECT *查找唯一行对于确定您应该在其中使用GROUP BY的哪一行。正如其他两个答案所指出的那样,您可以对GROUP BY(以及ORDER BY)使用多列,并以逗号分隔。

答案 2 :(得分:-1)

where子句放在group之前,如下所示: -

SELECT GROUP_CONCAT(client),staff,code from table 
where client IS NOT NULL AND staff  IS NOT NULL
GROUP BY staff,code