简体   繁体   English

SQL 根据多行值获取记录

[英]SQL Get Records based on multiple row value

I am trying to create a SQL report that can do logic based on a boolean that exists in multiple rows.我正在尝试创建一个 SQL 报告,该报告可以基于存在于多行中的 boolean 执行逻辑。 I created a bunch of fake data below, and my attempts.我在下面创建了一堆假数据,以及我的尝试。

IMPORT NOTE: I am writing this using SSMS but plan to run it in MySql.重要提示:我正在使用 SSMS 编写此代码,但计划在 MySql 中运行它。 Ran into some issues with temporary tables and "cannot re-open table..." so I decided to work with a familiar environment and work on porting things over as I have breakthroughs.遇到临时表和“无法重新打开表......”的一些问题,所以我决定在熟悉的环境中工作,并在我有突破时进行移植。

The way it exists in the DB is by joining two tables, lets call them display and displayschedule.它存在于数据库中的方式是通过连接两个表,我们称它们为 display 和 displayschedule。

a) display a) 显示

CREATE TABLE #tmp_display (
    DisId int,
    DisName varchar(255),
    DisActive tinyint,
    Descr varchar(255),
    DateModified datetime
)

INSERT INTO #tmp_display(DisId, DisName, DisActive, Descr, DateModified)
VALUES (4210, 'Test Display 1', 1, 'Test Display 1', GETDATE()),
       (1241, 'Test Display 2', 1, 'Test Display 2', GETDATE()),
       (8311, 'Test Display 3', 1, 'Test Display 3', GETDATE())

b) displayschedule b) 显示时间表

CREATE TABLE #tmp_displayschedule (
    DisSchedId int,
    DisId int,
    DisSchedName varchar(255),
    DisSchedAct tinyint,
    Descr varchar(255),
    DateModified datetime
)

INSERT INTO #tmp_displayschedule(DisSchedId, DisId, DisSchedName, DisSchedAct, Descr, DateModified)
VALUES (159123, 4210, 'Test Schedule 0', 0, 'OLD Schedule for Display 1 & 2', GETDATE() -1),
       (159123, 1241, 'Test Schedule 0', 0, 'OLD Schedule for Display 1 & 2', GETDATE() -1),
       (160213, 4210, 'Test Schedule 1', 0, 'Schedule for Display 1 & 2', GETDATE()),
       (160213, 4210, 'Test Schedule 1', 1, 'Schedule for Display 1 & 2', GETDATE()),
       (160213, 1241, 'Test Schedule 1', 1, 'Schedule for Display 1 & 2', GETDATE()),
       (160112, 8311, 'Test Schedule 2', 0, 'Schedule for Display 3', GETDATE()),
       (160112, 8311, 'Test Schedule 2', 1, 'Schedule for Display 3', GETDATE())

See the joined data:

SELECT * 
FROM #tmp_display dis
LEFT OUTER JOIN #tmp_displayschedule ds on dis.DisId = ds.DisId
ORDER BY ds.DateModified ASC

My attempt at a self join to get expected output:我尝试自我加入以获得预期的 output:

SELECT t1.DisId
FROM (
        SELECT dis.DisId
        FROM #tmp_display dis
        LEFT OUTER JOIN #tmp_displayschedule ds on dis.DisId = ds.DisId
        WHERE ds.DisSchedAct = 0
        GROUP BY dis.DisId
     ) as t1
JOIN
    (
        SELECT dis.DisId
        FROM #tmp_display dis
        LEFT OUTER JOIN #tmp_displayschedule ds on dis.DisId = ds.DisId
        WHERE ds.DisSchedAct = 1
        GROUP BY dis.DisId
     ) as t2 on t1.DisId = t2.DisId

My Current Output:我当前的 Output:

DisId
1241
4210
8311

My Expected Output:我预期的 Output:

DisId
4210
8311

What is causing the issue (i think): The fact that there is an OLD schedule id for DisId 1241 that has an inactive record but the fact that it exists in another schedule id and is active Im not sure how to factor this out.是什么导致了这个问题(我认为): DisId 1241 有一个旧的计划 ID,它有一个不活动的记录,但它存在于另一个计划 ID 中并且是活动的,我不知道如何解决这个问题。

I tried adding in the DisSchedId into the GROUP BY which gave me my result in SSMS, but did not give me anything in MySql.我尝试将 DisSchedId 添加到 GROUP BY 中,这给了我在 SSMS 中的结果,但在 MySql 中没有给我任何东西。

SELECT t1.DisId
FROM (
        SELECT dis.DisId, ds.DisSchedId
        FROM #tmp_display dis
        LEFT OUTER JOIN #tmp_displayschedule ds on dis.DisId = ds.DisId
        WHERE ds.DisSchedAct = 0
        GROUP BY dis.DisId, ds.DisSchedId
     ) as t1
JOIN
    (
        SELECT dis.DisId, ds.DisSchedId
        FROM #tmp_display dis
        LEFT OUTER JOIN #tmp_displayschedule ds on dis.DisId = ds.DisId
        WHERE ds.DisSchedAct = 1
        GROUP BY dis.DisId, ds.DisSchedId
     ) as t2 on t1.DisId = t2.DisId and t1.DisSchedId = t2.DisSchedId

Tested on MySQL 8.0.29:在 MySQL 8.0.29 上测试:

mysql> select d.DisId from tmp_display d 
       join tmp_displayschedule s on d.DisId = s.DisId 
       group by d.DisId, s.DisSchedId 
       having group_concat(distinct s.DisSchedAct order by s.DisSchedAct) = '0,1';
+-------+
| DisId |
+-------+
|  4210 |
|  8311 |
+-------+

That works for your sample data and desired result, but it may need some refinement for other cases.这适用于您的样本数据和所需的结果,但可能需要对其他情况进行一些改进。

Anyway, it demonstrates one solution for , which is the general type of task you're trying to solve.无论如何,它演示了一种用于的解决方案,这是您要解决的一般类型的任务。 Relational division is where you need a set of rows to all include specific values.关系除法是您需要一组行来全部包含特定值的地方。 It's sort of the complement to IN() but where the terms are combined with AND instead of OR .它是对IN()的补充,但这些术语与AND而不是OR结合使用。 You can follow that tag to see other past answers on Stack Overflow about relational division.您可以关注该标签以查看 Stack Overflow 上有关关系划分的其他过去答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM