我可以使用什么 SQL 选择查询来对每一行进行排序,然后对已排序的行进行排序?
例如:表格选项卡(c1、c2、c3、c4)
2,5,8,4
2,1,6,7
5,2,9,3
查询必须给出:
1,2,6,7
2,3,5,9
2,4,5,8
SELECT
MIN(c1, c2, c3, c4) AS new_c1,
CASE MIN(c1, c2, c3, c4) WHEN c1 THEN MIN(c2, c3, c4)
WHEN c2 THEN MIN(c1, c3, c4)
WHEN c3 THEN MIN(c1, c2, c4)
WHEN c4 THEN MIN(c1, c2, c3)
END AS new_c2,
CASE MAX(c1, c2, c3, c4) WHEN c1 THEN MAX(c2, c3, c4)
WHEN c2 THEN MAX(c1, c3, c4)
WHEN c3 THEN MAX(c1, c2, c4)
WHEN c4 THEN MAX(c1, c2, c3)
END AS new_c3,
MAX(c1, c2, c3, c4) AS new_c4
FROM tab
ORDER BY new_c1, new_c2, new_c3, new_c4
min()
和max()
功能引用:
请注意,当 max() [和 min()] 具有 2 个或更多参数时,它是一个简单的函数,但如果只给定一个参数,则作为聚合函数运行。
这只是开始,也许不是最“干净”的代码,但它会起作用
SELECT CASE WHEN C1 < C2 THEN
CASE WHEN C1 < C3 THEN C1 ELSE C3 END
ELSE
CASE WHEN C2 < C3 THEN C2 ELSE C3 END
END
From YourTable
这将首先选择最小的元素。再多三个,你就可以开始了。一旦你有了这个结果集,你就可以按第一列排序。
可能的解决方案:
CREATE TEMPORARY TABLE nums2
(
Row int,
V int
);
INSERT INTO nums2
SELECT *
FROM
(
SELECT rowid Row, c1 V FROM nums
UNION ALL
SELECT rowid Row, c2 V FROM nums
UNION ALL
SELECT rowid Row, c3 V FROM nums
UNION ALL
SELECT rowid Row, c4 V FROM nums
)
ORDER BY Row, V;
SELECT n1.V v1, n2.V v2, n3.V v3, n4.V v4
FROM nums2 n1
INNER JOIN nums2 n2 ON n1.Row = n2.Row AND n2.rowid = n1.rowid + 1
INNER JOIN nums2 n3 ON n1.Row = n3.Row AND n3.rowid = n1.rowid + 2
INNER JOIN nums2 n4 ON n1.Row = n4.Row AND n4.rowid = n1.rowid + 3
WHERE ((n1.rowid - 1) % 4 = 0)
ORDER BY n1.V, n2.V, n3.V, n4.V
它使用一个临时表 ( nums2
) 来保存“线性化”行,然后使用隐藏列rowid
将行分组。
测试人员:http ://sqlfiddle.com/#!7/d0232/38
最后一个选择可以简化一点:
SELECT n1.V v1, n2.V v2, n3.V v3, n4.V v4
FROM nums2 n1
INNER JOIN nums2 n2 ON n2.rowid = n1.rowid + 1
INNER JOIN nums2 n3 ON n3.rowid = n1.rowid + 2
INNER JOIN nums2 n4 ON n4.rowid = n1.rowid + 3
WHERE ((n1.rowid - 1) % 4 = 0)
ORDER BY n1.V, n2.V, n3.V, n4.V
因为WHERE
表达式将“选择”每一行的最小值。
测试人员:http ://sqlfiddle.com/#!7/d0232/39
查询很容易扩展。
您可以将表格旋转为(row_nr, col_nr, value)
格式。然后您可以对其进行排序,并将其还原为(row_nr, val1, val2, val3, val4)
格式。
; with with_numbers as
(
select row_number() over (order by c1) rn
, *
from tab
)
, normalized(rn, nr) as
(
select rn, c1 from with_numbers
union all
select rn, c2 from with_numbers
union all
select rn, c3 from with_numbers
union all
select rn, c4 from with_numbers
)
, normalized_with_number as
(
select row_number() over (partition by rn order by nr) rn2
, *
from normalized
)
, sorted as
(
select max(case when rn2 = 1 then nr end) c1
, max(case when rn2 = 2 then nr end) c2
, max(case when rn2 = 3 then nr end) c3
, max(case when rn2 = 4 then nr end) c4
from normalized_with_number
group by
rn
)
select *
from sorted
order by
c1
, c2
, c3
, c4