开发者

Ordered Value by Column / Row

Its a little difficult to explain. It might be easier to skip to the examples.

A table has an id and four columns that each allow null.

ID, Col1, Col2, Col3, Col4

There are x number of rows. ( Usually less than 4 ) And only up to 4 distinct values will be used across the columns.

I am looking to return up to 4 rows, where each row in the resulting set is basically a column value where the value is selected left from right starting at the top preserving Col number. If another row has a value that is not column unique it is shifted to the next available column.

Examples:

If I have:

ID, Col1, Col2, Col3, Col4  
0,  A   , B   ,     , C  
1,      ,     , D   ,

I would like to return

A  
B  
D  
C

and

ID, Col1, Col2, Col3, Col4  
0,  A   , B   , D   ,   
1,  C   ,     ,     ,

Gives

A  
B  
D  
C 

and

ID, Col1, Col2, Col3, Col4  
0,  A   , B   , D   ,   
1,  C   ,     ,     ,  
2,  C   ,     ,     ,

Gives

A  
B  
D  
C 

Thanks! The scenario when there are non unique columns and spaces between values can be thrown out.

This will not happen:

a,b,,d
c,,,

This might help:

CREATE TABLE #original ( id int ,A INT, B开发者_如何学C INT, C INT, D INT );

INSERT INTO #original
--SELECT 0,1,2,null,4
--union 
--select 1,null,null,3,null
--
--
--SELECT 0,1,2,3,null
--union 
--select 1,4,null,null,null
--
--
SELECT 0,1,2,4,null
union 
select 1,3,null,null,null 
union 
select 2,3,null,null,null 

select * from #original order by id asc;

with cteOriginal as
(
    select *, RANK() over (partition by [SortOrder] order by id asc) as [NonUniqueSortOrder]
    from
    (
        select id, A as [value], 1 as [SortOrder]
        from #original
        where A is not null
        union all
        select id, B as [value], 2 as [SortOrder]
        from #original
        where B is not null
        union all
        select id, C as [value], 3 as [SortOrder]
        from #original
        where C is not null
        union all
        select id, D as [value], 4 as [SortOrder]
        from #original
        where D is not null
    ) as temp
)

select [value] from
(
select top 50 [value], ((([NonUniqueSortOrder] - 1) * 4) + [SortOrder]) sortedOrder
from cteOriginal
order by sortedOrder
) tmp
group by [value]
order by min(sortedOrder)

DROP TABLE #original


Use:

SELECT DISTINCT COL1 AS col
  FROM YOUR_TABLE
 WHERE col1 IS NOT NULL
UNION
SELECT DISTINCT COL2 AS col
  FROM YOUR_TABLE
 WHERE col2 IS NOT NULL
UNION 
SELECT DISTINCT COL3 AS col
  FROM YOUR_TABLE
 WHERE col3 IS NOT NULL
UNION
SELECT DISTINCT COL4 AS col
  FROM YOUR_TABLE
 WHERE col4 IS NOT NULL
ORDER BY col

UNION will remove duplicates between the statements; DISTINCT will return a unique list of values per statement. UNION ALL would be faster than UNION, but it doesn't remove duplicates.


I may not understand everything that you described you wanted. From reading your problem and comments from others, I am guessing that this is what you are looking for:

Updated version:

with cteOriginal as
(
    select *, RANK() over (partition by [SortOrder] order by id asc) as [NonUniqueSortOrder]
    from
    (
        select id, A as [value], 1 as [SortOrder]
        from #original
        where A is not null
        union all
        select id, B as [value], 2 as [SortOrder]
        from #original
        where B is not null
        union all
        select id, C as [value], 3 as [SortOrder]
        from #original
        where C is not null
        union all
        select id, D as [value], 4 as [SortOrder]
        from #original
        where D is not null
    ) as temp
)
select [value]
from cteOriginal
where id = (select MIN(tmp.id) from cteOriginal tmp where tmp.value = cteOriginal.value)
order by ((([NonUniqueSortOrder] - 1) * 4) + [SortOrder])

I got rid of the duplicate values by picking the one with the smallest id, min(id). You can change it to use max(id).

Initial version:

with cteOriginal as
(
    select *, RANK() over (partition by [column] order by id asc) as [NonUniqueSortOrder]
    from
    (
        select id, A as [value], 'A' as [Column], 1 as [SortOrder]
        from #original
        where A is not null
        union all
        select id, B as [value], 'B' as [Column], 2 as [SortOrder]
        from #original
        where B is not null
        union all
        select id, C as [value], 'C' as [Column], 3 as [SortOrder]
        from #original
        where C is not null
        union all
        select id, D as [value], 'D' as [Column], 4 as [SortOrder]
        from #original
        where D is not null
    ) as temp
)
select [value]
from cteOriginal
order by ((([NonUniqueSortOrder] - 1) * 4) + [SortOrder])

By the way, I am using mssql 2005 for this query. Please comment and we'll refine it.


select value from (    
    select col1 as value from table_name where col1 is not null
     union
    select col2 as value from table_name where col2 is not null
     union
    select col3 as value from table_name where col3 is not null
     union
    select col4 as value from table_name where col4 is not null     
) order by value


Try this one

With MyTables as
(
SELECT  [Col1] as [ColX] FROM [Test].[dbo].[MyTable] 
Union 
SELECT  [Col2] as [ColX]   FROM [Test].[dbo].[MyTable]
Union
SELECT  [Col3] as [ColX]   FROM [Test].[dbo].[MyTable]
Union
SELECT  [Col4] as [ColX]   FROM [Test].[dbo].[MyTable]
)
select ColX from MyTables where ColX is not null
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜