根据项目的显示次数对项目进行排序

时间:2010-04-23 06:00:53

标签: sql sql-server tsql

我有这样的数据

d b c

a d

c b

a b

c a

c a d

c

如果你分析,你会发现每个元素的外观如下

a:4 b:3 c:5 d:2

根据外观,我的排序元素将是 C,A,B,d

,最终输出应为

c b d

a d

c b

a b

c a

c a d

C

有任何线索,我们如何使用sql查询实现这一目标?

1 个答案:

答案 0 :(得分:0)

除非有另一列指示输入行的顺序,否则将无法保证输出行以相同的顺序返回。我在这里假设通过三列值对它们进行排序,以便结果是确定性的。

可能可以将此代码压缩为更少的步骤,但可以合理地清楚地显示这些步骤。

请注意,对于大型数据集,将其中一些步骤划分为创建临时表或工作表的SELECT INTO操作可能更有效。

DECLARE @t TABLE
(col1 CHAR(1)
,col2 CHAR(1)
,col3 CHAR(1)
)

INSERT @t
      SELECT 'd','b','c'
UNION SELECT 'a','d',NULL
UNION SELECT 'c','b',NULL
UNION SELECT 'a','b',NULL
UNION SELECT 'c','a',NULL
UNION SELECT 'c','a','d'
UNION SELECT 'c',NULL,NULL


;WITH freqCTE
AS
(
        SELECT col1 FROM @t WHERE col1 IS NOT NULL

        UNION ALL

        SELECT col2 FROM @t WHERE col2 IS NOT NULL

        UNION ALL

        SELECT col3 FROM @t WHERE col3 IS NOT NULL        
)
,grpCTE
AS
(
        SELECT  col1    AS val
                ,COUNT(1) AS cnt
        FROM freqCTE
        GROUP BY col1

)
,rowNCTE
AS
(
                 SELECT *
                        ,ROW_NUMBER() OVER (ORDER BY col1
                                                     ,col2
                                                     ,col3
                                           ) AS rowN
                 FROM @t
)
,buildCTE
AS
(
        SELECT rowN
               ,val
               ,cnt
               ,ROW_NUMBER() OVER (PARTITION BY rowN
                                   ORDER BY     ISNULL(cnt,-1) DESC
                                               ,ISNULL(val,'z') 
                                   ) AS colOrd
        FROM (                           
                SELECT *
                FROM            rowNCTE  AS t
                JOIN            grpCTE   AS g1
                ON              g1.val = t.col1

                UNION ALL

                SELECT *
                FROM            rowNCTE  AS t
                LEFT JOIN       grpCTE   AS g2
                ON              g2.val = t.col2

                UNION ALL

                SELECT *
                FROM            rowNCTE  AS t
                LEFT JOIN       grpCTE   AS g3
                ON              g3.val = t.col3
            ) AS x
)
SELECT b1.val  AS col1
       ,b2.val AS col2
       ,b3.val AS col3
FROM buildCTE AS b1
JOIN buildCTE AS b2
ON   b2.rowN   = b1.rowN
AND  b2.colOrd = 2
JOIN buildCTE AS b3
ON   b3.rowN   = b1.rowN
AND  b3.colOrd = 3
WHERE b1.colOrd = 1
ORDER BY b1.rowN