【问题标题】:MySQL - Union or join?MySQL - 联合还是加入?
【发布时间】:2011-07-15 02:14:51
【问题描述】:

我正在尝试在一个 SQL 查询中收集统计数据,以便在联合中自动对日期进行排序。它实际上只有一张表,但我想统计不同的数据案例。

我的表看起来像这样:

ID   In          Wanted
441  2011-03-14  0
439  2011-03-14  1
442  2011-03-14  0
428  2011-03-13  1
431  2011-03-13  1
425  2011-03-11  0
423  2011-03-11  1
420  2011-03-09  1

我通过这个查询接近了预期的结果:

SELECT * FROM
(
  (SELECT date(In) n, count(date(In)) cntw, null cntl FROM items i WHERE Wanted=1 group by date(In))
union all
  (SELECT date(In) n, null cntw, count(date(In)) cntl FROM items i WHERE Wanted=0 group by date(In))
) Serie
Order by n DESC

但是 close 不够接近 :D 我得到的结果是这样的:

n            cntw   cntl
2011-03-14   null   2
2011-03-14   1      null
2011-03-13   2      null
2011-03-11   null   1
2011-03-11   1      null
2011-03-09   1      null

我想要的是按日期“混合”同一行的结果:

n            cntw   cntl
2011-03-14   1      2
2011-03-13   2      null
2011-03-11   1      1
2011-03-09   1      null

如您所见,每个日期只有一行。 实际上,最完美的结果是甚至还有缺失的日期:

n            cntw   cntl
2011-03-14   1      2
2011-03-13   2      null
2011-03-12   null   null
2011-03-11   1      1
2011-03-10   null   null
2011-03-09   1      null

...但我想这是不可能的。

谢谢!

【问题讨论】:

  • 您应该避免在字段名称中使用 MySQL 关键字(我的意思是 In 字段)。关于问题:不能以某种方式使用GROUP BY 吗?
  • 嗯,这个名字实际上是CheckIn 并且表格比我在这里展示的要复杂得多,我在我的例子中缩短了它。

标签: mysql join union


【解决方案1】:
select date(In) as n,
       sum(case when wanted = 1 then 1 else 0 end) as cntw,
       sum(case when wanted = 0 then 1 else 0 end) as cntl
    from items
    group by date(In)
    order by n desc

【讨论】:

  • 实际上,稍微玩一下,您的解决方案是最灵活的解决方案,我无需阅读 t 语法就可以理解它:DI 设法为您的模型添加更多高级选择。
【解决方案2】:

您将使用 LEFT JOIN 使用您的 n 字段来获取您有东西的日期...然后您将使用 UNION 这个查询来为您提供没有任何内容的行(信息您在上面给出的内容不允许我帮助查询这将是什么:D)。

【讨论】:

    【解决方案3】:

    你想加入他们,我认为这行得通

    SELECT * FROM
      (SELECT date(In) n, count(date(In)) cntw, null cntl FROM items i WHERE Wanted=1 group by date(In)) as a
    LEFT JOIN
      (SELECT date(In) n, null cntw, count(date(In)) cntl FROM items i WHERE Wanted=0 group by date(In)) as b
    ON a.n = b.n
    Order by n DESC
    

    但我认为这可以在一个查询中完成,也许像这样?

    CREATE TABLE #tmpFoo (
        SomeDate datetime,
        Wanted bit
    )
    
    INSERT INTO #tmpFoo VALUES ('2011-03-11', 0)
    INSERT INTO #tmpFoo VALUES ('2011-03-11', 1)
    INSERT INTO #tmpFoo VALUES ('2011-03-12', 0)
    INSERT INTO #tmpFoo VALUES ('2011-03-12', 1)
    INSERT INTO #tmpFoo VALUES ('2011-03-14', 0)
    
    SELECT  SomeDate n, 
            count(NULLIF(Wanted,0)) cntw, 
            count(NULLIF(Wanted,1)) cntl 
        FROM #tmpFoo i  
        GROUP BY SomeDate
    

    【讨论】:

    • 我会选择USING (N) 而不是ON a.n = b.n
    • @Romain,无论如何我都不喜欢这种方法,我在答案中添加了一个更简单、单一、无子查询的解决方案
    • +1v 谢谢!它就像一个魅力!我使用了 USING(n) 版本(来自 Romain)而不是 ON a.n = b.n。现在我会坐下来分析你做了什么,这样我就可以了解它是如何工作的:)
    • @Max Kielland,我写的第二个解决方案非常简单。您从查询中选择,按日期分组。 Count,将仅包含非 NULL 的值,因此,当 Wanted 字段不是您想要包含在计数中的值时,您使用 NULLIF 返回 null。这允许您在单个查询中计算两列。最初的创建表和插入只是在那里,所以我可以测试。
    • 嗯,我需要能够做一些更复杂的计算,比如count(NULLIF(Wanted,0) AND out IS NULL) cntw。我想你明白了,我需要使用更像 WHERE 语句来选择我需要计算的案例。
    猜你喜欢
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2021-07-20
    相关资源
    最近更新 更多