3

One of the columns in my table is "DataSource". Datasource can have two values, lets say "A" or "B". I would like to always take the row when Datasource = "A", however, if there isn't an entry for A I would like to take "B".

How does one do this in SQL Server?

EDIT:

So for a partucular product (Product ID) one Product ID may have two rows, each containing a different DataSource, wheres another ProductID may only have one DataSource:

{ProductID DataSource}
{1  A},
{1  B},
{2  B}

Here I would wish to select the top and bottom row

4
  • 1
    You need to explain your question a little bit better... Commented Jan 18, 2012 at 12:51
  • can you edit your question and put an example? Commented Jan 18, 2012 at 12:52
  • Are you selecting just one record from the whole table? Or are trying to get multiple records, excluding B's when A's exist? And if so, do you have other identifying fields so the A and B records can be related to each other? (Give some example data showing which records to include and which to exclude) Commented Jan 18, 2012 at 12:59
  • @user1107474 I've edited to work :) Commented Jan 18, 2012 at 13:14

5 Answers 5

2

A few options following your edit...

SELECT
  *
FROM
  table
WHERE
  DataSource = 'A'
  OR DataSource = 'B' AND NOT EXISTS (SELECT * FROM table AS lookup WHERE ProductID = table.ProductID AND DataSource = 'A')


SELECT
  *
FROM
  table
INNER JOIN
  (SELECT ProductID, MAX(DataSource) AS DataSource FROM table) AS lookup
    ON  lookup.ProductID  = table.ProductID
    AND lookup.DataSource = table.DataSource


WITH
  sequenced AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY ProductID ORDER BY DataSource) AS sequence_id
  FROM
    table
)
SELECT
  *
FROM
  sequenced
WHERE
  sequence_id = 1
Sign up to request clarification or add additional context in comments.

Comments

1
select ProductID from product where DataSource= 'A'
UNION
select id from DataSource where product not in (select ProductID from product where DataSource = 'A')

2 Comments

If there are no DataSource='A' records, you don't need to exclude them in the second part ...
@HansKesting - This covers three scenarios. Products having only DataSourceA, only DataSourceB, or having both data sources. Both and only A are covered by the first query, but only B is covered by the second.
1
SELECT top 1 * 
from YourTable 
ORDER BY DataSource ASC

Else

if the real values are NOT 'A' or 'B', which are just placeholders of @A and @B variables

SELECT top 1 * 
from YourTable 
ORDER BY CASE DataSource WHEN @A THEN 0 ELSE 1 END ASC

or

if there more variances than AB

SELECT top 1 * 
from YourTable 
ORDER BY CASE DataSource WHEN @A THEN 0 WHEN @B THEN 1 ELSE 2 END ASC

OR

If you need to group by ProductId

select * from (
SELECT *,
ROW_NUMBER OVER(PARTITION BY ProductId ORDER BY CASE DataSource WHEN @A THEN 0 WHEN @B THEN 1 ELSE 2 END ASC) ordinal
from YourTable 
) t
WHERE t.Ordinal = 1

1 Comment

My A and B are actually string-values, can I still use the second method?
0

Based on your sample data, this works:

SELECT ProductID, MIN(DataSource)
FROM @tab
GROUP BY ProductID;

And here is my test data:

declare @tab table (ProductID int, DataSource char(1))
insert into @tab values (1, 'A');
insert into @tab values (1, 'B');
insert into @tab values (2, 'B');

If there are more columns in the table than the two you show then:

SELECT T1.*
FROM @tab T1
JOIN
(
    SELECT ProductID, MIN(DataSource) AS DataSource
    FROM @tab
    GROUP BY ProductID
) T2 ON T1.ProductID = T2.ProductID AND T1.DataSource  = T2.DataSource

2 Comments

thanks, i will select this as the answer because of the use of Group by is helpful to me
Assumes no other fields exist in the table. (Which is the example given by the OP, so it works for that specific case.) To deal with other fields this is already embedded in the second option in my answer. [Following an edit, this now matches my second option]
0

ok, if I understood you requirement correctly then this would work

select TOP 1 * from yourtable where DATASOURCE = ISNULL(SELECT MAX(DATASOURCE) WHERE DATASOURCE="A","B")

The idea here is simple, you want to change DATASOURCE condition based on whether you have any rows of your first preference ("A") are available or not, if yes, then apply "A" condition or apply "B" condition

2 Comments

why it is a bad answer? this works perfect (not sure the best/optimized query), but this answer doesnt deserve a negetive
I don't know who down voted, but... The answer doesn't use TOP 1, so it's obviously a set based approach. In a set of data, it seems likely that there is a FK and that some FKs have DataSourceA, some FK's have DataSourceB and some FKs have both. In your case if ANY have DataSourceA then NONE of the records with only DataSouceB are returned.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.