假设我有三张桌子: 表A(键,值) 表B(键,值) TableC(键,值)
我希望为所有键返回一个值。如果TableC中存在键,则返回该值,否则,如果B中存在键,则返回该值,否则返回表A中的值
到目前为止,我提出的最好的是
SELECT key,Value
FROM TableA
WHERE key NOT IN (SELECT key FROM TableB)
AND key NOT IN (SELECT key FROM TableC)
UNION
SELECT key,Value
FROM TableB
WHERE key NOT IN (SELECT key FROM TableC)
UNION
SELECT key,Value
FROM TableC
但这似乎相当暴力。有人知道更好的方法吗?
编辑:这是一个更具体的例子。将TableA视为标准工作计划,其中键是日期,值是指定的班次。表B是覆盖标准工作周的法定假日日历。表C是一个例外时间表,当有人被要求进入并工作额外班次或不同班次时,用于覆盖其他两个时间表。
答案 0 :(得分:3)
好的,以你的具体例子为基础,我想出了一个与其他人发布的解决方案不同的解决方案(尽管我认为我更喜欢你的解决方案)。这是在MS SQL Server 2005上测试的 - 您的SQL方言可能需要更改。
首先,一些DDL设置阶段:
CREATE TABLE [dbo].[StandardSchedule](
[scheduledate] [datetime] NOT NULL,
[shift] [varchar](25) NOT NULL,
CONSTRAINT [PK_StandardSchedule] PRIMARY KEY CLUSTERED
( [scheduledate] ASC ));
CREATE TABLE [dbo].[HolidaySchedule](
[holidaydate] [datetime] NOT NULL,
[shift] [varchar](25) NOT NULL,
CONSTRAINT [PK_HolidaySchedule] PRIMARY KEY CLUSTERED
( [holidaydate] ASC ));
CREATE TABLE [dbo].[ExceptionSchedule](
[exceptiondate] [datetime] NOT NULL,
[shift] [varchar](25) NOT NULL,
CONSTRAINT [PK_ExceptionDate] PRIMARY KEY CLUSTERED
( [exceptiondate] ASC ));
INSERT INTO ExceptionSchedule VALUES ('2008.01.06', 'ExceptionShift1');
INSERT INTO ExceptionSchedule VALUES ('2008.01.08', 'ExceptionShift2');
INSERT INTO ExceptionSchedule VALUES ('2008.01.10', 'ExceptionShift3');
INSERT INTO HolidaySchedule VALUES ('2008.01.01', 'HolidayShift1');
INSERT INTO HolidaySchedule VALUES ('2008.01.06', 'HolidayShift2');
INSERT INTO HolidaySchedule VALUES ('2008.01.09', 'HolidayShift3');
INSERT INTO StandardSchedule VALUES ('2008.01.01', 'RegularShift1');
INSERT INTO StandardSchedule VALUES ('2008.01.02', 'RegularShift2');
INSERT INTO StandardSchedule VALUES ('2008.01.03', 'RegularShift3');
INSERT INTO StandardSchedule VALUES ('2008.01.04', 'RegularShift4');
INSERT INTO StandardSchedule VALUES ('2008.01.05', 'RegularShift5');
INSERT INTO StandardSchedule VALUES ('2008.01.07', 'RegularShift6');
INSERT INTO StandardSchedule VALUES ('2008.01.09', 'RegularShift7');
INSERT INTO StandardSchedule VALUES ('2008.01.10', 'RegularShift8');
使用这些表/行作为基础,此SELECT语句将检索所需的数据:
SELECT DISTINCT
COALESCE(e2.exceptiondate, e.exceptiondate, holidaydate, scheduledate) AS ShiftDate,
COALESCE(e2.shift, e.shift, h.shift, s.shift) AS Shift
FROM standardschedule s
FULL OUTER JOIN holidayschedule h ON s.scheduledate = h.holidaydate
FULL OUTER JOIN exceptionschedule e ON h.holidaydate = e.exceptiondate
FULL OUTER JOIN exceptionschedule e2 ON s.scheduledate = e2.exceptiondate
ORDER BY shiftdate
答案 1 :(得分:1)
这是一个备用SQL语句: -
SELECT
ALL_KEYS.KEY,
NVL( TABLEC.VALUE, NVL( TABLEB.VALUE, TABLEA.VALUE)) AS VALUE
FROM
(SELECT KEY AS KEY FROM TABLEA
UNION
SELECT KEY FROM TABLEB
UNION
SELECT KEY FROM TABLEC) ALL_KEYS,
TABLEA,
TABLEB,
TABLEC
WHERE
ALL_KEYS.KEY = TABLEA.KEY(+) AND
ALL_KEYS.KEY = TABLEB.KEY(+) AND
ALL_KEYS.KEY = TABLEC.KEY(+);
NB。 NVL()是Oracle函数。如果第一个参数为NULL,则返回第二个参数,否则返回第一个参数。你没有说你正在使用哪个数据库,但毫无疑问,所有数据库都有相应的数据。
答案 2 :(得分:0)
如果您有多个需要数据的表格,那么您将不得不从中进行选择,除此之外别无他法。
从你的SQL中,似乎你可以从tableC获得包含tableA和tableB中的键的restuls,因为你是在tableC上的一个简单select的restuls(其中没有where子句)。你在任何其他表中不存在的一组独有键之后的位置?如果是这样,那么你需要在tableB和tableC的选择中为tableA的where子句做你所做的。
我希望这是有道理的......
答案 3 :(得分:0)
您的查询看起来很好。
或者,您可以使用下面的查询并在客户端进行过滤。对数据库服务器来说压力会小一些。
SELECT key, value, 2 AS priority
FROM TableA
UNION
SELECT key, value, 1 AS priority
FROM TableB
UNION
SELECT key, value, 0 AS priority
FROM TableC
ORDER BY key, priority
答案 4 :(得分:0)
以下是我将如何在SQL Server中执行此操作。此解决方案应生成比原始逻辑IO更少的逻辑IO。如果表格足够大,我会交换到#temp表以启用并行性。
DECLARE @MyTable TABLE
(
Key int PRIMARY KEY,
Value int
)
--Grab from TableC
INSERT INTO @MyTable(Key, Value)
SELECT Key, Value
FROM TableC
--Grab from TableB
INSERT INTO @MyTable(Key, Value)
SELECT Key, Value
FROM TableB
WHERE Key not in (SELECT Key FROM @MyTable)
--Grab from TableA
INSERT INTO @MyTable(Key, Value)
SELECT Key, Value
FROM TableA
WHERE Key not in (SELECT Key FROM @MyTable)
--Pop the result
SELECT Key, Value
FROM @MyTable
这种技术反映了如何通过创建字典来处理C#中的3个列表。
答案 5 :(得分:0)
SELECT isnull( c.key, isnull( b.key, a.key) ) ,
isnull( c.value, isnull( b.value, a.value ) )
FROM TableA a
LEFT JOIN TableB b
ON a.key = b.key
LEFT JOIN TableC c
ON b.key = c.key
答案 6 :(得分:0)
创建所有键的主表,然后将此主表连接到三个表并调查COALESCE
命令。