2013-03-04 25 views
3

我有一個表Prices如何選擇SQL Server中多個列之間不是數字的所有值?

ID Price_1 Price_2 Price_3 

P1 10  11  12 
P2 13  14  15 
P3 aa  16  bb 
P4 19  cc  20 

正如你可以從上面看到,從列Price_1Price_2Price_3一些值可能不是數字。

我想要的是首先找到所有這些non-numeric values然後給出一個總結(concatenate所有非數值和列一個ID)

因此,對於上面的例子,我要的是

ID Bad_Columns  Bad_Values 
P3 Price_1,Price_3 aa,bb 
P4 Price_2   cc 

我該怎麼寫這個查詢?

+2

好吧,如果你想要某種類型的列值不好的審計表,那麼我強烈建議你不要**連接這些值,在數據庫上這樣做沒有意義。您可以爲每個列的每個不合格值使用同一個表。 – Lamak 2013-03-04 15:57:26

+0

@Lamak感謝您的建議。我只需要生成一個彙總表 – 2013-03-04 16:00:31

回答

2

你可以做這樣的事情:

WITH CTE AS 
( SELECT ID, Value, ColumnName 
    FROM Prices 
      UNPIVOT 
      ( Value 
       FOR ColumnName IN ([Price_1], [Price_2], [Price_3]) 
      ) upvt 
    WHERE ISNUMERIC(Value) = 0 
) 
SELECT ID, 
     BadColumns = STUFF((SELECT ', ' + ColumnName 
          FROM CTE 
          WHERE CTE.ID = t.ID 
          FOR XML PATH(''), TYPE 
         ).value('.', 'NVARCHAR(MAX)'), 1, 2, ''), 
     BadValues = STUFF((SELECT ', ' + Value 
          FROM CTE 
          WHERE CTE.ID = t.ID 
          FOR XML PATH(''), TYPE 
         ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') 
FROM (SELECT DISTINCT ID FROM CTE) t 

第一部分UNPIVOTs查詢得到的列行,那麼第二部分將串連「壞」行成一列。

Example on SQL Fiddle

+0

對不起,我還添加了bad_columns以及如何適應這種情況? – 2013-03-04 15:59:39

+0

我可以在觸發器內使用'WITH ... AS ...'嗎?我得到錯誤:'CTE'附近的語法不正確。' – 2013-03-04 16:14:56

+0

在觸發器內部使用它沒有問題,您需要確保'WITH'之前的行以分號結尾(或者在分號之前放置一個分號'WITH')。 – GarethD 2013-03-04 16:19:21

0

您可以使用這將unpivot的的數據可以再使用串聯的FOR XML PATH值:

;with cte as 
(
    select id, col, data 
    from 
    (
    select t.id, 
     c.col, 
     case c.col 
     when 'Price_1' then Price_1 
     when 'Price_2' then Price_2 
     when 'Price_3' then Price_3 
     end as data 
    from yourtable t 
    cross join 
    (
     select 'Price_1' as col 
     union all select 'Price_2' 
     union all select 'Price_3' 
    ) c 
) src 
    where isnumeric(data) = 0 
) 
select distinct c1.id, 
    stuff((select ', ' + col 
     from cte c2 
     where c1.id = c2.id 
     FOR XML PATH ('')) 
      , 1, 1, '') AS Bad_columns, 
    stuff((select ', ' + data 
     from cte c2 
     where c1.id = c2.id 
     FOR XML PATH ('')) 
      , 1, 1, '') AS Bad_Values 
from cte c1 

SQL Fiddle with Demo

這也可以使用unpivot功能寫着:

;with cte as 
(
  select id, col, data 
  from yourtable 
  unpivot 
  (
    data 
    for col in ([Price_1], [Price_2], [Price_3]) 
 ) unpiv 
  where isnumeric(data) = 0 
) 
select distinct c1.id, 
  stuff((select ', ' + col 
         from cte c2 
         where c1.id = c2.id 
         FOR XML PATH ('')) 
          , 1, 1, '')  AS Bad_columns, 
  stuff((select ', ' + data 
         from cte c2 
         where c1.id = c2.id 
         FOR XML PATH ('')) 
          , 1, 1, '')  AS Bad_Values 
from cte c1 

SQL Fiddle with Demo。其結果是:

| ID |  BAD_COLUMNS | BAD_VALUES | 
--------------------------------------- 
| P3 | Price_1, Price_3 |  aa, bb | 
| P4 |   Price_2 |   cc | 
0

我建議:

select p.* 
from ((select id, price_1 as price, 'price_1' as col) union all 
     (select id, price_2 as price, 'price_2' as col) union all 
     (select id, price_3 as price, 'price_3' as col) 
    ) p 
where is_numeric(price) = 0 and price is not null 

如果你真的想他們你的格式,只是做:

select id, 
     stuff((case when isnumeric(price_1) = 1 then ',Price_1' else '' end) + 
      (case when isnumeric(price_2) = 1 then ',Price_2' else '' end) + 
      (case when isnumeric(price_3) = 1 then ',Price_3' else '' end) 
      ), 1, 1, '') as Bad_Columns, 
     stuff((case when isnumeric(price_1) = 1 then ','+Price_1 else '' end) + 
      (case when isnumeric(price_2) = 1 then ','+Price_2 else '' end) + 
      (case when isnumeric(price_3) = 1 then ','+Price_3 else '' end) 
      ), 1, 1, '') as Bad_Values 
from p 
where isnumeric(price_1) = 0 or isnumeric(price_2)= 0 or isnumeric(price_3) = 0 

,我不是原因使用unpivot是因爲它假定列類型是兼容的。如果您想將其擴展到更多列,請使用Excel生成代碼。

相關問題