SQL 查询左侧加入问题

SQL query left joining issue

我有两个 table:usersuserlogs

table1
----------
id | name
----------
1 | A
2 | B
3 | C
4 | D


table2
----------
user_id | date
----------
1 | 2015-12-17
2 | 2015-12-18
3 | 2015-12-19
4 | 2015-12-20

如果我对所选日期进行 LEFT JOIN,它只会提供存在于 table 2.

中的数据
SELECT r.user_id, count(r.user_id) as count
FROM table1 a LEFT OUTER JOIN table2 r ON ( r.user_id = a.id )
WHERE r.created_at BETWEEN '2015-12-17' AND '2015-12-19'
GROUP BY a.id

我得到以下

Result
----------
user_id | count
----------
1 | 1
2 | 1
3 | 1

我需要如下内容:

Result
----------
user_id | count
----------
1 | 1
2 | 1
3 | 1
4 | 0

我尝试了很多不同的方法,但都没有成功。

尝试将过滤条件移动到左连接中。

SELECT 
   a.id, 
   count(r.user_id) as count
FROM table1 a 
LEFT OUTER JOIN table2 r ON r.user_id = a.id AND 
                            r.created_at BETWEEN '2015-12-17' AND '2015-12-19'
GROUP BY a.id

这个查询应该没问题:

DECLARE @T1 TABLE
(
    id INT
    , name VARCHAR(50)
);

DECLARE @T2 TABLE
(
    [user_id] INT
    , [date] DATE
);

INSERT INTO @T1 (id, name)
VALUES (1, 'A'), (2, 'B'), (3, 'C'), (4, 'D');

INSERT INTO @T2 ([user_id], [date])
VALUES (1, '2015-12-17'), (2, '2015-12-18'), (3, '2015-12-19'), (4, '2015-12-20');

SELECT T1.id, COALESCE(T2.Cnt, 0) AS Cnt
FROM (SELECT DISTINCT id FROM @T1) AS T1
LEFT JOIN (
    SELECT [user_id], COUNT(*) AS Cnt
    FROM @T2
    WHERE [date] BETWEEN '2015-12-17' AND '2015-12-19'
    GROUP BY [user_id]
    ) AS T2
    ON T2.[user_id] = t1.id;

它输出你所期望的:)

或者像这样将其包装在存储过程中:

CREATE PROCEDURE dbo.YourProcedure
(
    @company_id INT
    , @start_date DATE
    , @end_date DATE
)
as
SELECT T1.id
    , T1.department_id
    , COALESCE(T2.cnt, 0) AS cnt
FROM (
    SELECT DISTINCT id, department_id
    FROM users
    WHERE company_id = @company_id
    ) AS T1
LEFT JOIN (
    SELECT user_id, COUNT(*) AS cnt
    FROM userlogs
    WHERE created_at BETWEEN @start_date AND @end_date
    GROUP BY user_id
    ) AS T2
    ON T2.user_id = t1.id;

只需将变量传递给它即可调用它。 Using a stored procedure in Laravel 4 解释如何操作。

如果您在 WHERE 子句中使用 LEFT OUTER JOIN 指定的过滤列,则 Join 的行为与 INNER JOIN 完全相同。如果您不希望将 LEFT JOIN 的行为更改为 INNER JOIN,则转到 ON & AND 条件。

    SELECT * FROM TABLE1 T1
    LEFT OUTER JOIN TABLE2 T2 ON T1.ID = T2.USER_ID
    WHERE T2.DATE BETWEEN '2015-12-17' AND '2015-12-19'

同下

    SELECT * FROM TABLE1 T1
    INNER JOIN TABLE2 T2 ON T1.ID = T2.USER_ID
    WHERE T2.DATE BETWEEN '2015-12-17' AND '2015-12-19'

在你的情况下你需要去

    SELECT * FROM TABLE1 T1
    LEFT OUTER JOIN TABLE2 T2 ON T1.ID = T2.USER_ID 
    AND T2.DATE BETWEEN '2015-12-17' AND '2015-12-19'