通过不在另一个表中显示SQL中的特定行

通过不在另一个表中显示SQL中的特定行,sql,mariadb,Sql,Mariadb,我在高级SQL和stackoverflow方面不是很有经验,所以我会尽力解释我需要什么 假设我有一张名为“Shift”的表和一张名为“Schedule”的表 “班次”包含“班次id、班次开始、班次结束、班次日期、, shift\u函数\u id' shift\U start表示开始时间 shift_end表示结束时间 shift_day表示从0到6开始的一周中的天数 星期天 shift_function_id表示属于shift的函数_id “计划”包含“计划id、计划日期、计划开始、, 计划\结

我在高级SQL和stackoverflow方面不是很有经验,所以我会尽力解释我需要什么

假设我有一张名为“Shift”的表和一张名为“Schedule”的表

“班次”包含“班次id、班次开始、班次结束、班次日期、, shift\u函数\u id'

shift\U start表示开始时间

shift_end表示结束时间

shift_day表示从0到6开始的一周中的天数 星期天

shift_function_id表示属于shift的函数_id

“计划”包含“计划id、计划日期、计划开始、, 计划\结束,计划\功能\ id'

schedule_date表示计划的日期

schedule_start表示开始时间

schedule_end表示结束时间

schedule_function_id表示属于 时间表

我想做的是,如果表“Schedule”中不存在来自“Shift”的行,且该行具有给定的特定日期,其中Shift\u start=Schedule\u start和Shift\u end=Schedule\u end和Shift\u function\u id=Schedule\u function\u id,则显示该行

下面是一个例子:

SELECT shift_id, shift_day, shift_start, shift_end, function_id, function_name, function_color
FROM Shift
LEFT JOIN Function
ON function_id = shift_function_id
WHERE shift_day = $day
AND NOT EXISTS (
    SELECT 1
    FROM Schedule
    WHERE schedule_date = '$date' AND schedule_start = shift_start AND schedule_end = shift_end AND schedule_function_id = shift_function_id
)
ORDER BY function_name, shift_start, shift_end;
问题是

如果有两个班次具有相同的开始和结束时间,并且表“Schedule”包含一行具有相同的函数id和开始和结束时间,则两个班次都不会显示

以下是表格内容的示例:

时间表

移位

“Shift”中的两行不再显示

我想要什么

如果“Schedule”只有一行包含与“Shift”中给定数据相同的信息,我希望显示另一行

如果“Schedule”有两行具有相同信息,则不显示任何行。它只需要取决于“Schedule”中有多少行具有相同的信息

图像

如果未填写任何内容,则显示起始和结束相同的两行

当我放置一个具有相同开始和结束时间的记录时,它会删除两个移位行

我需要这个,当我只填写一个记录相同的开始和结束时间


我能想到的唯一方法是让NOT EXISTS子句删除所有行,只需使用MIN或MAX Shift_id从重复行中追加1行即可-

SELECT shift_id, 
       shift_day, 
       shift_start, 
       shift_end, 
       function_id, 
       function_name, 
       function_color 
FROM   shift 
       LEFT JOIN function 
              ON function_id = shift_function_id 
WHERE  shift_day = $day 
       AND NOT EXISTS (SELECT 1 
                       FROM   schedule 
                       WHERE  schedule_date = '$date' 
                              AND schedule_start = shift_start 
                              AND schedule_end = shift_end 
                              AND schedule_function_id = shift_function_id) 
UNION ALL 
SELECT Min(S1.shift_id), 
       S1.shift_day, 
       S1.shift_start, 
       S1.shift_end, 
       function_id, 
       function_name, 
       function_color 
FROM   shift S1 
       JOIN shift S2 
         ON S1.shift_id <> S2.shift_id 
            AND S1.shift_day = S2.shift_day 
            AND S1.shift_start = S2.shift_start 
            AND S1.shift_end = S2.shift_end 
       LEFT JOIN function 
              ON function_id = S1.shift_function_id 
GROUP  BY S1.shift_day, 
          S1.shift_start, 
          S1.shift_end, 
          function_id, 
          function_name, 
          function_color 
ORDER  BY function_name, 
          shift_start, 
          shift_end;

是工作示例。

如果您的MariaDB版本支持窗口函数,则可以在子查询中使用行号来消除记录的歧义,这些记录在shift_表中具有相同的shift_开始、shift_结束、shift_函数,或者在schedule表中具有相同的schedule_开始、schedule_结束、schedule_函数

然后可以在连接条件中使用记录列组,我将notexits子查询更改为LEFT-join反模式,但这基本上是相同的逻辑

select s.*, f.*
from (
    select 
        s.*, 
        row_number() over(
            partition by shift_start, shift_end, shift_function 
            order by shift_id
        ) rn
    from shift s
    where shift_day = @shift_day
) s
left join (
    select 
        c.*,
        row_number() over(
            partition by schedule_start, schedule_end, schedule_function 
            order by schedule_id
        ) rn
    from schedule c
    where schedule_date = @schedule_date
) c 
    on  c.schedule_start = s.shift_start 
    and c.schedule_end = s.shift_end
    and c.schedule_function_id = s.shift_function_id
    and c.rn = s.rn
left join function f
    on f.function_id = s.shift_function_id
where c.rn is null
order by f.function_name, s.shift_start, s.shift_end

你的完美要求还不清楚。请编辑您的问题,并发布更多示例数据和预期结果。@AnkitBajpai我已添加图像。也许这会让事情变得更清楚我很确定这是比我的更好的解决方案。
SELECT shift_id, 
       shift_day, 
       shift_start, 
       shift_end, 
       function_id, 
       function_name, 
       function_color 
FROM   shift 
       LEFT JOIN function 
              ON function_id = shift_function_id 
WHERE  shift_day = $day 
       AND NOT EXISTS (SELECT 1 
                       FROM   schedule 
                       WHERE  schedule_date = '$date' 
                              AND schedule_start = shift_start 
                              AND schedule_end = shift_end 
                              AND schedule_function_id = shift_function_id) 
UNION ALL 
SELECT Min(S1.shift_id), 
       S1.shift_day, 
       S1.shift_start, 
       S1.shift_end, 
       function_id, 
       function_name, 
       function_color 
FROM   shift S1 
       JOIN shift S2 
         ON S1.shift_id <> S2.shift_id 
            AND S1.shift_day = S2.shift_day 
            AND S1.shift_start = S2.shift_start 
            AND S1.shift_end = S2.shift_end 
       LEFT JOIN function 
              ON function_id = S1.shift_function_id 
GROUP  BY S1.shift_day, 
          S1.shift_start, 
          S1.shift_end, 
          function_id, 
          function_name, 
          function_color 
ORDER  BY function_name, 
          shift_start, 
          shift_end;
select s.*, f.*
from (
    select 
        s.*, 
        row_number() over(
            partition by shift_start, shift_end, shift_function 
            order by shift_id
        ) rn
    from shift s
    where shift_day = @shift_day
) s
left join (
    select 
        c.*,
        row_number() over(
            partition by schedule_start, schedule_end, schedule_function 
            order by schedule_id
        ) rn
    from schedule c
    where schedule_date = @schedule_date
) c 
    on  c.schedule_start = s.shift_start 
    and c.schedule_end = s.shift_end
    and c.schedule_function_id = s.shift_function_id
    and c.rn = s.rn
left join function f
    on f.function_id = s.shift_function_id
where c.rn is null
order by f.function_name, s.shift_start, s.shift_end