【问题标题】:Select column using different WHERE clause from a different table使用来自不同表的不同 WHERE 子句选择列
【发布时间】:2019-06-17 23:55:26
【问题描述】:

就像这里提出的许多问题一样,我需要能够使用 2 个不同的 WHERE 子句选择同一列两次。不幸的是,有一个问题,因为我也在尝试解决另一个常见问题,由于 WHERE 子句,当我使用 COUNT() 时,即使使用 LEFT JOIN,也不是所有的单元格都显示出来。

所以有两个问题。首先,WHERE 子句删除了一个有 NULL 的选项,尽管有 LEFT JOIN。

其次,由于 WHERE 子句,我无法将 2 个查询合并为一个。

我已经尝试使用“CASE WHEN”和内部和外部的 COUNT()、子查询、OUTER APPLY 和 UNION。它们都没有显示我需要什么。

所以我的第一张桌子显示了学生和他们的校舍:

Table - Houses

StudentID | House
---------------------
    1     |  A
    2     |  B
    3     |  C
    4     |  D
    5     |  A
    6     |  B
    7     |  C
    8     |  D

第二张表显示房子点数:

Table - Points
StudentID | House | PointAwardedDate
------------------|-------------------
    1     |  A    |      01/04/2019 10:04:00
    1     |  A    |      17/05/2019 11:25:00
    1     |  A    |      17/06/2019 12:58:00
    2     |  B    |      02/02/2019 08:54:00
    3     |  C    |      03/03/2019 15:46:00
    4     |  D    |      17/06/2019 13:14:00
    5     |  A    |      05/06/2019 15:34:00
    6     |  B    |      01/02/2019 12:32:00
    7     |  C    |      17/06/2019 11:57:00
    8     |  D    |      15/04/2019 09:24:00
    8     |  D    |      17/06/2019 09:45:00

使用以下代码,我可以选择自上周日(2019 年 6 月 16 日)以来颁发的奖项,并显示每所房子获得了多少奖项:

SELECT
Houses.House,
COUNT(Points.StudentID) AS PointsCount
FROM Houses
LEFT JOIN Points
ON Houses.STudentID = Points.StudentID
WHERE Points.PointsAwardedDate >= (SELECT DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
GROUP BY Houses.House

哪个显示

House  |  PointsCount
-------|--------------
  A    |      1
  C    |      1
  D    |      2

问题 1:我需要这样显示该表:

House  |  PointsCount
-------|--------------
  A    |      1
  B    |      0
  C    |      1
  D    |      2

问题 2 - 我们需要显示另一列,其中包含整个学年的分数。所以我们拥有的代码(有效)是:

SELECT DISTINCT
    Houses.House,
COUNT(Points.StudentID) AS PointsCountYear
FROM Houses
LEFT JOIN Points
ON Houses.STudentID = Points.StudentID
WHERE Points.PointsAwardedDate >= (
    SELECT 
        TOP 1 Points.PointsAwardedDate
    FROM TblSchoolManagementTermDates
    WHERE Points.PointsAwardedDate <= 
        CONVERT(datetime, GETDATE())
            AND intTerm = 1
        ORDER BY intSchoolYear DESC)
AND txtDate <= (
    SELECT TOP 1 txtFinishDate
    FROM TblSchoolManagementTermDates
    WHERE txtFinishDate >= 
        CONVERT(datetime, GETDATE())
        ORDER BY intSchoolYear ASC)
GROUP BY Pups.txtAcademicHouse

此处的学期日期为 2018 年 9 月 1 日 - 2019 年 8 月 31 日

这会拉出下表:

House  |  PointsCountYear
-------|-----------------
  A    |      4
  B    |      2
  C    |      2
  D    |      3

我们需要能够将这两个组合在一起,所以我们的决赛桌看起来像这样:

House  |  PointsCount |  PointsCountYear
-------|--------------|-----------------
  A    |      1       |      4
  B    |      0       |      2
  C    |      1       |      2
  D    |      2       |      3

我们知道第一部分的问题在于 WHERE 子句过滤掉 House B 的任何数据,因此即使使用 LEFT JOIN 也不会显示,但我们不确定如何在另一个中呈现方式,同时仍然保留正确的数据。

非常感谢任何帮助。

谢谢 抢

【问题讨论】:

  • 将 where 谓词移动到连接谓词。此外,您应该决定使用哪个 DBMS 作为 mysql sql server。
  • 请注意,您的 Points 表中的 House 列是不需要的,只有在与其他表不同步时才会造成麻烦。除非学生可以更换房屋,否则您的房屋表应该被移除。
  • 抱歉,好地方@Jerry,积分表中不应该有房子列。不知道为什么我把它放在那里。我认为是星期一早上的事情。

标签: sql


【解决方案1】:

您可以使用条件聚合来做到这一点:

SELECT
  h.House,
  SUM(CASE 
    WHEN p.PointsAwardedDate >= DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6) THEN 1
    ELSE 0
  END)  AS PointsCount,
  SUM(CASE 
    WHEN p.PointsAwardedDate >= '2018-09-01' AND p.PointsAwardedDate < '2019-09-01'  THEN 1
    ELSE 0
  END) AS PointsCountYear
FROM Houses AS h
LEFT JOIN Points AS p
ON h.STudentID = p.StudentID
GROUP BY h.House

请参阅demo
结果:

> House | PointsCount | PointsCountYear
> :---- | ----------: | --------------:
> A     |           1 |               4
> B     |           0 |               2
> C     |           1 |               2
> D     |           2 |               3

【讨论】:

  • 就是这个!删除查询并从 COUNT() 更改为 SUM() 已经破解了它。谢谢你
【解决方案2】:

我尝试回答 SQLServer: 问题1的可能解决方案:

CREATE TABLE #HOUSES
(
  STUDENT_ID INT NOT NULL
, HOUSE VARCHAR(1) NOT NULL
);

INSERT INTO #HOUSES  VALUES (1, 'A')
, (2, 'B')
, (3, 'C')
, (4, 'D')
, (5, 'A')
, (6, 'B')
, (7, 'C')
, (8, 'D');

CREATE TABLE #POINTS
(
  STUDENT_ID INT NOT NULL
, HOUSE VARCHAR(1) NOT NULL
, POINTAWARDEDDATE DATE NOT NULL
);

INSERT INTO #POINTS  VALUES 
(1, 'A', '01/04/2019 10:04:00'), 
(1, 'A', '17/05/2019 11:25:00'), 
(1, 'A', '17/06/2019 12:58:00'), 
(2, 'B', '02/02/2019 08:54:00'), 
(3, 'C', '03/03/2019 15:46:00'), 
(4, 'D', '17/06/2019 13:14:00'), 
(5, 'A', '05/06/2019 15:34:00'), 
(6, 'B', '01/02/2019 12:32:00'), 
(7, 'C', '17/06/2019 11:57:00'), 
(8, 'D', '15/04/2019 09:24:00'), 
(8, 'D', '17/06/2019 09:45:00')
;

SELECT H.HOUSE
    , COUNT(P.POINTAWARDEDDATE) AS POINTSCOUNT
FROM
(
SELECT HOUSE
FROM #HOUSES
GROUP BY HOUSE) H
LEFT JOIN #POINTS P
ON H.HOUSE = P.HOUSE
AND P.POINTAWARDEDDATE >= (SELECT DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
GROUP BY H.HOUSE

结果:

HOUSE, POINTSCOUNT
A   1
B   0
C   1
D   2

【讨论】:

  • 这看起来不错,但不幸的是,正如我在上面的评论中提到的,我犯了一个错误。 Points 表中没有 House 列。
【解决方案3】:

试试这个

SELECT h.house
    , COUNT(P.PointsAwardedDate) AS POINTSCOUNT
FROM
(
SELECT StudentId,house
FROM HOUSES
) H
LEFT JOIN POINTS P
ON H.[StudentId] = P.StudentId
AND P.[PointsAwardedDate] >= (SELECT DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
GROUP BY h.house

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多