【问题标题】:How to create a query for this scenario?如何为此场景创建查询?
【发布时间】:2017-09-21 09:05:20
【问题描述】:

我已尽一切努力使预期结果显示为输出,但没有运气。

示例数据库

表1

 CalendarDate Date

表2

User VarChar(50)
WDT DateTime

Table1 记录

 CalendarDate
 2017-01-01
 2017-01-02
 2017-01-03
 2017-01-04

表2记录

 WDT                         User
 2017-01-01 08:00:00.000     User1
 2017-01-02 08:05:00.000     USer1

预期结果

 User     CalendarDate    Status     WDT            Time
 User1    2017-01-01      Present    2017-01-01     08:00:00.000 
 User1    2017-01-02      Present    2017-01-02     08:00:00.000
 User1    2017-01-03      Absent     Null           Null
 User1    2017-01-04      Absent     Null           Null

即使Table2上没有记录,我也想显示日期,然后如果Table2在Table1 CalendarDate上为null,则显示状态

【问题讨论】:

  • 您应该添加您想要实现的目标。从您的示例中,我猜您想知道每个用户在 Table1 中所有日子的存在/缺席?
  • 即使Table2上没有记录我也想显示日期,然后在Table1 CalendarDate上Table2为空时显示状态
  • 你怎么能说 2017 年 1 月 3 日、2017 年 1 月 4 日日期的用户 1,因为表 2 中没有这些日期
  • select ... from table2 右外连接 table1 ...
  • Harvy,您在同一天提出了两个请求,(到目前为止)使您获得了-5 和-3 的反对票。这些当之无愧的投票是为了让其他人为你做你的工作。如果您尝试过某事,请在问题中展示,否则人们根本不会相信您已经尝试过。

标签: sql sql-server


【解决方案1】:

使用左连接

select t1.CalendarDate, t2.[User], case when t2.[User] is null then 'Absent' else 'Present' end [Status], CAST(t2.wdt as date) WDT, CAST(t2.wdt as time) [Time]
from Table1 t1
left join Table2 t2 on t1.CalendarDate = CAST(t2.wdt as date)

CalendarDate    User    Status  WDT         Time
2017-09-22      User1   Present 2017-09-22  11:23:19.2730000
2017-09-23      User1   Present 2017-09-23  11:23:19.2730000
2017-09-24      NULL    Absent  NULL        NULL
2017-09-25      NULL    Absent  NULL        NULL

如果您还需要列 [User] 来处理不匹配的行,您需要添加与用户表的连接或从表 2 中提取用户列表,例如:

select t1.CalendarDate, u.[User], case when t2.[User] is null then 'Absent' else 'Present' end [Status], CAST(t2.wdt as date) WDT, CAST(t2.wdt as time) [Time]
from Table1 t1
cross join (select distinct [User] from Table2) u
left join Table2 t2 on t1.CalendarDate = CAST(t2.wdt as date) and u.[User] = t2.[User]

CalendarDate    User    Status  WDT         Time
2017-09-22      User1   Present 2017-09-22  11:30:05.4800000
2017-09-23      User1   Present 2017-09-23  11:30:05.4800000
2017-09-24      User1   Absent  NULL        NULL
2017-09-25      User1   Absent  NULL        NULL

【讨论】:

  • 用户为空,这不是预期的结果
【解决方案2】:

我认为您可以尝试使用此方法获取所有用户的列表(在这种情况下与表用户左连接是不够的 - 请参阅下面的示例数据):

SELECT C.USERNAME, A.CALENDARDATE
      , CASE WHEN B.USERNAME IS NULL THEN 'Absent' ELSE 'Present' END AS STATUS
      , CAST(B.WDT AS DATE) AS WDT, CAST(B.WDT AS TIME) AS TIME
FROM CALENDAR A
CROSS JOIN (SELECT DISTINCT USERNAME FROM US) C
LEFT JOIN US B ON A.CALENDARDATE = CAST(WDT AS DATE) AND C.USERNAME=B.USERNAME;

样本数据:

SET DATEFORMAT ymd

CREATE TABLE CALENDAR (CALENDARDATE DATE);
INSERT INTO CALENDAR VALUES ('2017-01-01');
INSERT INTO CALENDAR VALUES ('2017-01-02');
INSERT INTO CALENDAR VALUES ('2017-01-03');
INSERT INTO CALENDAR VALUES ('2017-01-04');

CREATE TABLE US (USERNAME VARCHAR(10), WDT DATETIME);
INSERT INTO US VALUES ('User1', '2017-01-01 08:00');
INSERT INTO US VALUES ('User1', '2017-01-02 08:05');
INSERT INTO US VALUES ('User2', '2017-01-04 08:10');

输出:

   +----------+--------------+---------+------------+------------------+
| USERNAME | CALENDARDATE | STATUS  |    WDT     |       TIME       |
+----------+--------------+---------+------------+------------------+
| User1    | 2017-01-01   | Present | 2017-01-01 | 08:00:00.0000000 |
| User1    | 2017-01-02   | Present | 2017-01-02 | 08:05:00.0000000 |
| User1    | 2017-01-03   | Absent  | NULL       | NULL             |
| User1    | 2017-01-04   | Absent  | NULL       | NULL             |
| User2    | 2017-01-01   | Absent  | NULL       | NULL             |
| User2    | 2017-01-02   | Absent  | NULL       | NULL             |
| User2    | 2017-01-03   | Absent  | NULL       | NULL             |
| User2    | 2017-01-04   | Present | 2017-01-04 | 08:10:00.0000000 |
+----------+--------------+---------+------------+------------------+

【讨论】:

    【解决方案3】:

    左连接可以,但在用户字段中返回空值,除非您对其进行硬编码

    select [USER],convert( varchar(10),t1.Calenderdate,120) Calenderdate ,
     case when convert( varchar(10),t2.WDT,120)  =  convert( varchar(10),t1.Calenderdate,120) then 'Present'
     else 'Absent' end Status, convert( varchar(10),t2.WDT,120) WDT,
     CAST(t2.WDT AS TIME) AS TIME 
     from 
     #tab1 t1 LEFT join #tab2 t2 on 
     convert( varchar(10),t2.WDT,120)  =  convert( varchar(10),t1.Calenderdate,120) 
    

    【讨论】:

    • 没有这样的“Calenderdate”拼写错误,而且用户不能有空值
    【解决方案4】:

    你的意思是这样的?

            DECLARE @Table1 TABLE ([CalendarDate] DATE)
        DECLARE @Table2 TABLE ([User] VarChar(50), [WDT] DateTiME)
    
        INSERT INTO @Table1 VALUES 
        ('2017-01-01'),
        ('2017-01-02'),
        ('2017-01-03'),
        ('2017-01-04')
    
        INSERT INTO @Table2 VALUES
        ('User1', '2017-01-01 08:00:00.000'),
        ('User1', '2017-01-02 08:05:00.000')
    
    
        SELECT  ISNULL(t2.[User], 'User1') AS [User],
                t1.CalendarDate,
                CASE WHEN t2.[User] IS NOT NULL THEN 'Present' ELSE 'Absent' END AS Status,
                CAST(t2.WDT AS DATE) AS WDT,
                CAST(t2.WDT AS TIME) AS Time
        FROM @Table2 t2
        RIGHT JOIN @Table1 t1
        ON CAST(t2.WDT AS DATE) = t1.CalendarDate
    

    【讨论】:

    • ISNULL(t2.[empuser], 'User1') 这个创建的用户在记录中不存在
    • 是的,我当然知道.. 但它的输出是他想要的。我想他会认为他没有这方面的数据
    猜你喜欢
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    相关资源
    最近更新 更多