web-dev-qa-db-ja.com

SQL Server結合がレコードを返さない

LEFT JOINに基づいて、join_dateを使用してすべてのユーザーを返そうとしているクエリがあります。クエリは次のようになります。

SELECT users.name,
MIN(history.time_out) as join_date
FROM flexlm_user users
LEFT JOIN flexlm_history history ON users.id=history.user_id
GROUP BY users.name
ORDER BY 2

ただし、結果は、history.time_inがNullであるjoin_dateに対してNullを返します。履歴テーブルには、time_outフィールドのNullがありません。どんな助けでも大歓迎です。

現在の結果はこのようなものです

name    join_date
user1   NULL
user2   NULL
user3   NULL
user4   48:00.0
user5   31:00.0
user6   59:00.0
user7   15:00.0

このような結果が欲しい:

name    join_date
user1   13:00.0
user2   5:00.0
user3   7:00.0
user4   4:00.0
user5   31:00.0
user6   59:00.0
user7   15:00.0

履歴テーブル:

CREATE TABLE [dbo].[flexlm_history](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [server_id] [int] NOT NULL,
    [user_id] [int] NOT NULL,
    [product_id] [int] NOT NULL,
    [update_id] [int] NOT NULL,
    [time_out] [datetime] NOT NULL,
    [time_in] [datetime] NULL
)

サンプルデータ:

+-----+-----------+---------+------------+-----------+-------------------------+-------------------------+
| id  | server_id | user_id | product_id | update_id |        time_out         |         time_in         |
+-----+-----------+---------+------------+-----------+-------------------------+-------------------------+
| 615 |         2 |       9 |          8 |      4670 | 2017-07-28 14:10:00.000 | 2017-07-28 14:43:00.000 |
| 616 |         2 |       9 |         10 |      4670 | 2017-07-28 14:10:00.000 | 2017-07-28 14:43:00.000 |
| 617 |         2 |      24 |          9 |      4672 | 2017-07-28 14:13:00.000 | NULL                    |
| 618 |         2 |       2 |          9 |      4672 | 2017-07-28 14:14:00.000 | NULL                    |
| 619 |         2 |      76 |          4 |      4676 | 2017-07-28 14:42:00.000 | 2017-07-28 16:53:00.000 |
| 620 |         3 |      18 |         20 |      4685 | 2017-07-28 15:22:00.000 | 2017-07-28 15:53:00.000 |
| 621 |         2 |      21 |          4 |      4686 | 2017-07-28 15:29:00.000 | 2017-07-28 16:33:00.000 |
| 622 |         2 |      24 |          4 |      4690 | 2017-07-28 15:48:00.000 | 2017-07-28 16:33:00.000 |
| 623 |         2 |       9 |          2 |      4692 | 2017-07-28 15:53:00.000 | 2017-07-28 16:43:00.000 |
| 624 |         2 |       9 |          8 |      4692 | 2017-07-28 15:53:00.000 | 2017-07-28 16:43:00.000 |
| 625 |         2 |       9 |         10 |      4692 | 2017-07-28 15:53:00.000 | 2017-07-28 16:43:00.000 |
| 626 |         2 |      43 |          2 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
| 627 |         2 |      43 |          5 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
| 628 |         2 |      43 |          6 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
| 629 |         2 |      43 |          8 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
| 630 |         2 |      43 |          9 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
| 631 |         2 |      43 |         10 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
| 632 |         2 |      43 |         11 |      4694 | 2017-07-28 16:10:00.000 | NULL                    |
+-----+-----------+---------+------------+-----------+-------------------------+-------------------------+

ユーザーテーブル:

CREATE TABLE [dbo].[flexlm_user](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [varchar](25) NOT NULL,
)

サンプルデータ:

+----+-------+
| id | name  |
+----+-------+
|  9 | user1 |
| 24 | user2 |
| 76 | user3 |
|  2 | user4 |
| 18 | user5 |
| 21 | user6 |
| 24 | user7 |
|  9 | user8 |
| 43 | user9 |
+----+-------+
2
its30

oUTER APPLYルートに行くのはどうですか。 nullを別の方法で処理するように内部クエリを変更できますが、私はそれらを無視しましたが、それらを処理したい場合は、将来的にISNULLまたはCASEを使用できます。

SELECT users.name,
       H.join_date
FROM flexlm_user users
    OUTER APPLY
(
    SELECT MIN(history.time_out) AS join_date
    FROM flexlm_history history
    WHERE history.user_id = users.id
          AND history.time_out IS NOT NULL
) H
ORDER BY H.join_date;
1
Ollie

このクエリは必要に応じて機能するはずです。すべてのユーザーとそのjoin_date(ユーザーがいる場合)が表示されます。

SELECT users.name
    , History.join_date
FROM flexlm_user AS users
    LEFT OUTER JOIN (
                    SELECT H.user_id, MIN(H.time_out) AS join_date
                    FROM flexlm_history AS H
                    GROUP BY H.user_id
                    ) AS History ON History.user_id = users.id
ORDER BY History.join_date;

Join_dateを持つユーザーのみを表示する必要がある場合は、代わりにINNER JOINに変更します。

1
Jonathan Fite