2011-05-04 71 views
4

我试图用IN子句执行SELECT,我希望能够以与我的列表中IN列表中的元素相同的顺序返回结果。例如:SQL - 根据查询参数保留排序

SELECT * FROM orders WHERE order_no IN ('B123', 'B483', 'B100', 'B932', ...); 

我想让他们以相同的顺序回来。理想情况下,这将会是巨大的,如果我能有这样一个说法:使用CASEDECODE关键字来定义某种自定义排序的查询

SELECT * FROM orders WHERE order_no IN ('B123', 'B483', 'B100', 'B932', ...) 
ORDER BY ('B123', 'B483', 'B100', 'B932', ...); 

我见过的例子。但是,在所有这些例子中,它们的排序都是针对一组预定的选项。然而,我的排序是完全依赖于什么我的用户进入他们的搜索条件,所以有可能是2个选项列表或100名单通过订购...

任何想法?有些Oracle功能我不知道,或者有些使用CASEDECODE进行动态设置的方法?

+1

在MySQL中,你可以做'ORDER BY FIELD( 'order_no', 'B123', 'B483', 'B100' ...)',但我不知道是否有一个Oracle等价物。 – 2011-05-04 16:18:43

+1

ORDER BY DECODE(order_no,'B123',1,'B483',2,'B100',3,...,1000)'?你显然必须建立正确的'DECODE'子句。 – NPE 2011-05-04 16:26:32

回答

4

值插入到一个临时表,并加入你选择了这一点。

然后你可以做你的临时表列中的自然顺序。

CREATE GLOBAL TEMPORARY TABLE sort_table (
    value  VARCHAR2(100), 
    sort_order NUMBER 
) ON COMMIT DELETE ROWS; 

INSERT INTO sort_table VALUES ('B123',1); 
INSERT INTO sort_table VALUES ('B483',2); 
... etc. ... 

select * from mytable 
inner join sort_table 
on mytable.mycolumn = sort_table.value 
order by sort_table.sort_order; 

要清除临时表,只需要COMMIT

+1

你在正确的轨道上,但你需要第二列来保存序列号和排序。 – 2011-05-04 16:24:12

+0

该语法不适用于Oracle – 2011-05-04 17:40:59

+0

Oracle-ised .... – 2011-05-05 01:29:49

-1

我不是一个Python的家伙,但在这里就是我会做它在PHP中,我希望你的想法。

  1. 建立一个像这样的字符串:

    $海峡= “( 'B123', 'B483', 'B100', 'B932',...)”;

    针对上述情况,你可以使用一个for循环或东西来构建一个很长的字符串。

  2. 插入字符串中像这样的查询:

$MyQuery = "SELECT * FROM orders WHERE order_no IN $str 
ORDER BY $str"; 

就像我说的,这是一个PHP的例子,但我相信你的想法。

+1

您使用的数据库是?我不认为'ORDER BY'支持这样的元素列表。 : - \ – kafuchau 2011-05-04 16:23:30

+0

我无法看到在任何SQL实现中,这可能如何工作*即使在理论上也是如此。 – 2011-05-05 01:24:23

2

我不知道是否有这个优雅的(或短)的解决方案。

如果你能动态地构建查询,下面应该工作:

WITH numbers AS (
    SELECT 1 as sort_order, 'B123' as order_no FROM DUAL 
    union all 
    SELECT 2 as sort_order, 'B483' as order_no FROM DUAL 
    union all 
    SELECT 2 as sort_order, 'B100' as order_no FROM DUAL 
    union all 
    SELECT 2 as sort_order, 'B932' as order_no FROM DUAL 
) 
SELECT orders.* 
FROM numbers 
    LEFT JOIN orders ON orders.ord_no = numbers.ord_no 
ORDER BY numbers.sort_order 
+0

with语句规则。 +1 – EvilTeach 2011-05-04 17:25:47

+0

+1最佳答案:) – 2014-02-19 05:05:24

1

您可以通过INSTR它串联变量和顺序如下图所示。我不能保证这种效率 - 但必须是Okey.Your前端显然必须做更多的工作。但是像这样构建一个查询可以打开sql注入。

SELECT * FROM orders WHERE order_no IN ('B123', 'B483', 'B100', 'B932', ...) 
ORDER BY 
    instr ('@[email protected]'|| '@[email protected]'||'@[email protected]'||'@[email protected]'||... ,'@'|| order_no||'@') 
+0

不错的做法 - 适用于一小部分短值。 – 2011-05-05 02:35:28

1

如果你想与DECODE去分配一个数值排序顺序:

SELECT ID FROM tbl WHERE ID IN (2,3,1) 
ORDER BY DECODE(ID, 2, 1, 3, 2, 3) 
2

你可以试试它会正常工作。检查下面的SQL: -

SELECT * FROM orders WHERE order_no IN ('B123', 'B483', 'B100', 'B932') 
ORDER BY DECODE(order_no,'B123','1','B483','2','B100','3','B932','4'); 
+0

这适用于我,但只有在1,2,3,4周围没有单引号... – ruben056 2017-04-13 05:54:30

+0

在DECODE中可以使用多达9个,而不是更多。如果我有更多,只有第一个值是正确的(Oracle数据库11g版本11.2.0.4.0 - 64位生产) – Punnerud 2017-10-25 11:25:48