SQL 服务器查询与 Oracle 查询相同吗?
Is the SQL Server query same as Oracle query?
由于 SQL 服务器不允许比较两列(例如,where (store_nbr, item_id)),我很难比较查询,尤其是当表有大量数据。
我有 3 张桌子
我有以下 Oracle 查询
FORCE_TAGS_SQL = """UPDATE /*+ dynamic_sampling(0) index(store_item store_item_pk) */ store_item SET user_bit_5 = '1'
WHERE (store_nbr, item_id) in (SELECT /*+ dynamic_sampling(0) index(tag_demand tag_demand_ix1) */ d.store_nbr, d.item_id
FROM store s, tag_demand d
WHERE s.division_id = 'XYZ'
AND d.store_nbr = s.store_nbr
AND d.print_dt = TRUNC(TO_DATE('2022-04-13', 'YYYY-MM-DD')))
AND user_bit_5 = '0'
"""
以下是转换后的SQL服务器查询
FORCE_TAGS_SQL = """UPDATE STORE_ITEM SET user_bit_5 = '1'
WHERE (store_nbr) in (SELECT d.store_nbr
FROM STORE s, tag_demand d
WHERE s.division_id = 'XYZ'
AND d.store_nbr = s.store_nbr
AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13')))
AND (item_id) in (SELECT d.item_id
FROM STORE s, tag_demand d
WHERE s.division_id = 'XYZ'
AND d.store_nbr = s.store_nbr
AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13')))
AND user_bit_5 = '0'
"""
SQL 服务器查询与 Oracle 查询相同吗?
更新:
UPDATE store_item SET user_bit_5 = '1'
FROM store_item item INNER JOIN tag_demand d
ON d.store_nbr = item.store_nbr AND d.item_id = item.item_id
WHERE d.store_nbr in ((SELECT s.store_nbr FROM STORE s WHERE s.division_id = 'XYZ')) AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13'))
更新#2:
FORCE_TAGS_SQL = """UPDATE STORE_ITEM SET user_bit_5 = '1'
FROM STORE_ITEM
inner join (
SELECT d.store_nbr, d.item_id
FROM store s, tag_demand d
WHERE d.store_nbr = s.store_nbr AND s.division_id = 'XYZ' AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13'))
) tagdemand
on tagdemand.store_nbr = STORE_ITEM.store_nbr
AND tagdemand.item_id = STORE_ITEM.item_id
where user_bit_5 = '0'
"""
更新#3
FORCE_TAGS_SQL = """UPDATE STORE_ITEM SET user_bit_5 = '1'
FROM STORE_ITEM
INNER JOIN tag_demand
ON
STORE_ITEM.item_id = tag_demand.item_id
AND STORE_ITEM.store_nbr = tag_demand.store_nbr
AND tag_demand.print_dt = '2022-04-11'
AND tag_demand.STORE_NBR in (SELECT store_nbr FROM store WHERE division_id = 'XYZ')
where user_bit_5 = '0'
"""
如果您想要相同的逻辑,可以使用 CONCAT()
。我无法告诉您这会使查询速度减慢多少。
WHERE (CONCAT(store_nbr, item_id)) in
(SELECT CONCAT(d.store_nbr, d.item_id)
FROM...)
区别在于您的 SQL 服务器版本更加自由。在 oracle 版本将接受 (A,1) 和 (B,2) 的情况下,即使这些组合不存在,您的 SQL 服务器版本也将接受 (A,2) 和 (B,1)在 sub-query.
一个简单的测试是检查从同一数据返回的行数。如果SQL服务器版本returns多行就知道有问题了。
您可能应该重构为 exists 而不是尝试在列表中使用子选择,因为这很可能会给您不同的结果。
...
WHERE EXISTS (SELECT *
FROM ...
JOIN ...
WHERE store.store_nbr = store_item.store_nbr
AND tag_demand.item_id = store_item.item_id
AND tag_demand.print_dt = ...)
顺便说一句,使用 JOIN 而不是 CARTESIAN PRODUCT 和 RESTRICTION 的组合(在 WHERE 子句“à la” Oracle 中错误加入!)。这是您用纯 SQL ISO 标准 1992 重写的查询:
UPDATE store_item
SET user_bit_5 = '1'
WHERE (store_nbr, item_id) in (SELECT d.store_nbr, d.item_id
FROM store s
JOIN tag_demand d
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13')
AND user_bit_5 = '0';
一种解决方案是使用 相关 IN :
UPDATE T
SET user_bit_5 = '1'
FROM store_item AS T
WHERE (store_nbr) in (SELECT d.store_nbr
FROM store s
JOIN tag_demand d
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13'
AND d.item_id = T.item_id)
AND user_bit_5 = '0';
另一个是在UPDATE中使用JOIN:
UPDATE T
SET user_bit_5 = '1'
FROM store_item AS T
JOIN tag_demand d
ON T.store_nbr = d.store_nbr
AND T.item_id = d. item_id
JOIN store s
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13'
AND user_bit_5 = '0';
我的首选解决方案是使用具有双重相关性的 EXISTS:
UPDATE store_item
SET user_bit_5 = '1'
WHERE EXISTS(SELECT 0/0
FROM store s
JOIN tag_demand d
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13'
AND store_itme.store_nbr = d.store_nbr
AND store_itme.item_id = d.item_id)
AND user_bit_5 = '0'
有些解决方案可以使用 INTERSECT 运算符,但需要了解 table 说明,尤其是 PK
具有 CONCAT 函数或类似...的所有其他解决方案将在结果集中产生误报行值。
由于 SQL 服务器不允许比较两列(例如,where (store_nbr, item_id)),我很难比较查询,尤其是当表有大量数据。
我有 3 张桌子
我有以下 Oracle 查询
FORCE_TAGS_SQL = """UPDATE /*+ dynamic_sampling(0) index(store_item store_item_pk) */ store_item SET user_bit_5 = '1'
WHERE (store_nbr, item_id) in (SELECT /*+ dynamic_sampling(0) index(tag_demand tag_demand_ix1) */ d.store_nbr, d.item_id
FROM store s, tag_demand d
WHERE s.division_id = 'XYZ'
AND d.store_nbr = s.store_nbr
AND d.print_dt = TRUNC(TO_DATE('2022-04-13', 'YYYY-MM-DD')))
AND user_bit_5 = '0'
"""
以下是转换后的SQL服务器查询
FORCE_TAGS_SQL = """UPDATE STORE_ITEM SET user_bit_5 = '1'
WHERE (store_nbr) in (SELECT d.store_nbr
FROM STORE s, tag_demand d
WHERE s.division_id = 'XYZ'
AND d.store_nbr = s.store_nbr
AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13')))
AND (item_id) in (SELECT d.item_id
FROM STORE s, tag_demand d
WHERE s.division_id = 'XYZ'
AND d.store_nbr = s.store_nbr
AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13')))
AND user_bit_5 = '0'
"""
SQL 服务器查询与 Oracle 查询相同吗?
更新:
UPDATE store_item SET user_bit_5 = '1'
FROM store_item item INNER JOIN tag_demand d
ON d.store_nbr = item.store_nbr AND d.item_id = item.item_id
WHERE d.store_nbr in ((SELECT s.store_nbr FROM STORE s WHERE s.division_id = 'XYZ')) AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13'))
更新#2:
FORCE_TAGS_SQL = """UPDATE STORE_ITEM SET user_bit_5 = '1'
FROM STORE_ITEM
inner join (
SELECT d.store_nbr, d.item_id
FROM store s, tag_demand d
WHERE d.store_nbr = s.store_nbr AND s.division_id = 'XYZ' AND d.print_dt = CONVERT(DATETIME, CONVERT(DATE, '2022-04-13'))
) tagdemand
on tagdemand.store_nbr = STORE_ITEM.store_nbr
AND tagdemand.item_id = STORE_ITEM.item_id
where user_bit_5 = '0'
"""
更新#3
FORCE_TAGS_SQL = """UPDATE STORE_ITEM SET user_bit_5 = '1'
FROM STORE_ITEM
INNER JOIN tag_demand
ON
STORE_ITEM.item_id = tag_demand.item_id
AND STORE_ITEM.store_nbr = tag_demand.store_nbr
AND tag_demand.print_dt = '2022-04-11'
AND tag_demand.STORE_NBR in (SELECT store_nbr FROM store WHERE division_id = 'XYZ')
where user_bit_5 = '0'
"""
如果您想要相同的逻辑,可以使用 CONCAT()
。我无法告诉您这会使查询速度减慢多少。
WHERE (CONCAT(store_nbr, item_id)) in
(SELECT CONCAT(d.store_nbr, d.item_id)
FROM...)
区别在于您的 SQL 服务器版本更加自由。在 oracle 版本将接受 (A,1) 和 (B,2) 的情况下,即使这些组合不存在,您的 SQL 服务器版本也将接受 (A,2) 和 (B,1)在 sub-query.
一个简单的测试是检查从同一数据返回的行数。如果SQL服务器版本returns多行就知道有问题了。
您可能应该重构为 exists 而不是尝试在列表中使用子选择,因为这很可能会给您不同的结果。
...
WHERE EXISTS (SELECT *
FROM ...
JOIN ...
WHERE store.store_nbr = store_item.store_nbr
AND tag_demand.item_id = store_item.item_id
AND tag_demand.print_dt = ...)
顺便说一句,使用 JOIN 而不是 CARTESIAN PRODUCT 和 RESTRICTION 的组合(在 WHERE 子句“à la” Oracle 中错误加入!)。这是您用纯 SQL ISO 标准 1992 重写的查询:
UPDATE store_item
SET user_bit_5 = '1'
WHERE (store_nbr, item_id) in (SELECT d.store_nbr, d.item_id
FROM store s
JOIN tag_demand d
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13')
AND user_bit_5 = '0';
一种解决方案是使用 相关 IN :
UPDATE T
SET user_bit_5 = '1'
FROM store_item AS T
WHERE (store_nbr) in (SELECT d.store_nbr
FROM store s
JOIN tag_demand d
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13'
AND d.item_id = T.item_id)
AND user_bit_5 = '0';
另一个是在UPDATE中使用JOIN:
UPDATE T
SET user_bit_5 = '1'
FROM store_item AS T
JOIN tag_demand d
ON T.store_nbr = d.store_nbr
AND T.item_id = d. item_id
JOIN store s
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13'
AND user_bit_5 = '0';
我的首选解决方案是使用具有双重相关性的 EXISTS:
UPDATE store_item
SET user_bit_5 = '1'
WHERE EXISTS(SELECT 0/0
FROM store s
JOIN tag_demand d
ON d.store_nbr = s.store_nbr
WHERE s.division_id = 'XYZ'
AND d.print_dt = '2022-04-13'
AND store_itme.store_nbr = d.store_nbr
AND store_itme.item_id = d.item_id)
AND user_bit_5 = '0'
有些解决方案可以使用 INTERSECT 运算符,但需要了解 table 说明,尤其是 PK
具有 CONCAT 函数或类似...的所有其他解决方案将在结果集中产生误报行值。