我有以下用于查询的SQL语句:
SELECT
DATE '1900-01-01' + FLOOR("DDate" / 1000) * INTERVAL'1' YEAR+ (MOD("DDate", 1000) -1) * INTERVAL'1' DAY AS "Date",
LTRIM((SUBSTR("NR8", -6)), '0') AS "Nr",
CASE WHEN "tEnd" =240000 THEN '23:59:59' ELSE REPLACE(TO_CHAR("tEnd", '00,00,00'),',',':') END AS "End",
REPLACE(TO_CHAR("zBegin", '00,00,00'),',',':') AS "tStart",
"Doc1" AS "Doc",
"Order" AS "Order"
FROM "MP002"."KKI1001"
WHERE "DDate" >119000
AND "tFact" = 1
ORDER BY "Date", "Order"
由于这大约是15mio记录,所以我只想接收必要的数据集。 Oracle数据库“ KKI1100”包含列“ Doc1”和列“ Type”。 但是,现在,我只希望来自“ KKI1001”的所有数据集,这些数据集在“ KKI1100”的“类型”列中包含X,X1或X2。
应如何实施? 使用联接和where子句? 还是有一种更优雅的方法?
答案 0 :(得分:1)
如果我是你,我只是将第二个表与第一个表进行内部连接,就像这样:
SELECT DATE '1900-01-01' + floor(k1."DDate" / 1000) * INTERVAL '1' YEAR + (MOD(k1."DDate", 1000) - 1) * INTERVAL '1' DAY AS "Date",
ltrim((substr(k1."NR8", -6)), '0') AS "Nr",
CASE
WHEN k1."tEnd" = 240000 THEN
'23:59:59'
ELSE
REPLACE(to_char(k1."tEnd", '00,00,00'), ',', ':')
END AS "End",
REPLACE(to_char(k1."zBegin", '00,00,00'), ',', ':') AS "tStart",
k1."Doc1" AS "Doc",
k1."Order" AS "Order"
FROM "MP002"."KKI1001" k1
INNER JOIN "KKI1100" k2 ON k1."Doc1" = k2."Doc2" AND k2."Type" IN ('X', 'X1', 'X2')
WHERE k1."DDate" > 119000
AND k1."tFact" = 1
ORDER BY "Date",
"Order";
您可以移动k2."Type" in ('X', 'X1', 'X2') down into the
where`子句;过滤谓词所在的内部联接实际上并不重要(外部联接则很重要,具体取决于您希望看到的结果)。
我假设KKI1100。“ Doc1”是唯一列。如果它不是唯一的,那么我建议使用exists
谓词,大致如下:
SELECT DATE '1900-01-01' + floor(k1."DDate" / 1000) * INTERVAL '1' YEAR + (MOD(k1."DDate", 1000) - 1) * INTERVAL '1' DAY AS "Date",
ltrim((substr(k1."NR8", -6)), '0') AS "Nr",
CASE
WHEN k1."tEnd" = 240000 THEN
'23:59:59'
ELSE
REPLACE(to_char(k1."tEnd", '00,00,00'), ',', ':')
END AS "End",
REPLACE(to_char(k1."zBegin", '00,00,00'), ',', ':') AS "tStart",
k1."Doc1" AS "Doc",
k1."Order" AS "Order"
FROM "MP002"."KKI1001" k1
WHERE k1."DDate" > 119000
AND k1."tFact" = 1
AND EXISTS (SELECT NULL
FROM "KKI1100" k2
WHERE k2."Type" in ('X', 'X1', 'X2')
AND k2."Doc1" = k1."Doc1")
ORDER BY "Date",
"Order";
答案 1 :(得分:1)
目前还不清楚表之间的关系。是否在两个表中都提到了Doc1
列?无论如何,您似乎想要一个IN
或EXISTS
子句。像这样:
...
WHERE ddate >119000
AND tfact = 1
AND doc1 IN
(
SELECT doc1
FROM kki1100
WHERE type IN ('X', 'X1', 'X2')
)
ORDER BY "Date", "Order";
在WHERE
子句中有它所属的条件。您可以使用EXISTS
代替IN
。我更喜欢IN
,因为它很简单。
关于性能考虑,重新编写查询应该是最后要考虑的事情。我们宁愿提供适当的索引。我不知道您选择标准的选择性。也许仅tfact = 1
会导致行数很少吗?还是ddate >119000
?还是只有两者的结合?还是对某些KKI1100条目的限制?好了,您可以为每种情况提供许多索引,然后查看使用的索引并删除其他的索引:
CREATE INDEX idx1 ON kki1001 (ddate, tfact, doc1);
CREATE INDEX idx2 ON kki1001 (tfact, ddate, doc1);
CREATE INDEX idx3 ON kki1001 (doc1, tfact, ddate);
CREATE INDEX idx4 ON kki1100 (doc1, type);
CREATE INDEX idx5 ON kki1100 (type, doc1);
答案 2 :(得分:0)
为避免where in子句或重复的OR子句,您可以尝试在X1,X2,X3的子查询上使用内部联接
SELECT
DATE '1900-01-01' + FLOOR("DDate" / 1000) * INTERVAL'1' YEAR+ (MOD("DDate", 1000) -1) * INTERVAL'1' DAY AS "Date",
LTRIM((SUBSTR("NR8", -6)), '0') AS "Nr",
CASE WHEN "tEnd" =240000 THEN '23:59:59' ELSE REPLACE(TO_CHAR("tEnd", '00,00,00'),',',':') END AS "End",
REPLACE(TO_CHAR("zBegin", '00,00,00'),',',':') AS "tStart",
"Doc1" AS "Doc",
"Order" AS "Order"
FROM "MP002"."KKI1001"
INNER JOIN (
select 'X1' as type from dual
union
select 'X2' as type from dual
union
select 'X3' as type from dual
) t on t.tpe = "KKI1001".type
WHERE "DDate" >119000
AND "tFact" = 1