我有一个ITEM
表,我希望返回由IN子句中通知的相同订单排序的结果。这些ID由用户通知。
今天我有这个:
SELECT *
FROM ITEM
WHERE ITEM_ID IN (45,2,671,6)
ORDER BY CASE ITEM_ID
WHEN 45 THEN 0
WHEN 2 THEN 1
WHEN 671 THEN 2
WHEN 6 THEN 3
END
这有效,但CASE
有limit个65535个参数,当我需要更多时,它会给我ORA-00939: too many arguments for function
。
是否有针对Oracle的替代解决方案,没有限制,最好具有良好的性能,并且在其他DBMS中也可以接受?
由于
答案 0 :(得分:1)
元素来自哪里?我建议您使用join
:
SELECT i.*
FROM ITEM i JOIN
(SELECT 45 as id, 1 as ord FROM DUAL UNION ALL
SELECT 2 as id, 2 as ord FROM DUAL UNION ALL
SELECT 671 as id, 3 as ord FROM DUAL UNION ALL
SELECT 6 as id, 4 as ord FROM DUAL
) x
ON i.ITEM_ID = x.id
ORDER BY x.ord;
如果id来自包含相关信息的表格,这会更简单。
答案 1 :(得分:1)
虽然您的逻辑和上述解决方案适用于小规模,但如果您谈论超过65000项,则需要一个可扩展的解决方案。
我的建议是将此任务分为两步。
第1步
创建一个临时表, 这个临时表将有3列最小值
TEMP_ITEM_ORDER_TABLE (
session_key varchar2(50),
item_id number,
item_report_order number
)
每次用户订购此类查询时,都会将数据(即项目ID及其序列号)插入此临时表中,并使用一些唯一键来标识用户会话(可能是用户ID或会话ID)。这个技巧是为了避免多个用户同时触发报告时项目列表发生冲突。
第2步
现在触发您的报表查询加入主表,临时表与session_key
。在基于输入顺序的查询顺序数据中(已存储在临时表中)
SELECT
T1.* , T2.item_report_order
FROM ITEM T1, TEMP_ITEM_ORDER_TABLE T2
WHERE T1.ITEM_ID = T2.ITEM_ID
AND T2.session_key = :input_session_key
ORDER BY t2.item_report_order
此方法
注意:为了进一步提高查询性能,在session_key上创建索引,临时表中的item_id也在ITEM表上的item_id上创建索引(如果尚未存在)
编辑: Oracle提供Global Temporary Table功能,该功能创建的功能只允许在会话中进行记录,并在会话提交/结束时自动清理等。您可以使用此功能并避免会话密钥,但此解决方案不能复制到其他数据库产品上,除非它们支持类似功能。
答案 2 :(得分:0)
您无需创建临时表,而是可以使用集合:
SELECT i.*
FROM ITEM i
INNER JOIN
(
SELECT ROWNUM AS rn,
COLUMN_VALUE AS value
FROM TABLE( :your_array )
) v
ON ( i.ITEM_ID = v.VALUE )
ORDER BY v.RN;
它甚至可以作为C# MVC pass data from one action method to another传递:
type=button