Querying columnar data in SQL Server - sql

I have a table structured as shown below
CustimerId Name Store Bill Item1 Item2 Item3
1 A StoreA 100 Y
2 A StoreB 200 N Y
3 B StoreA 300 N
4 C StoreC 400 Y N Y
Now I want to make one column based on the values in columns Item1, Item2, Item3 which is as below.
CustimerId Name Store Bill BoughtAnySpecialItem
1 A StoreA 100 Y
2 A StoreB 200 Y
3 B StoreA 300 N
4 C StoreC 400 Y
This means if any of the value in columns through Item1 to Item3 is 'Y' I want to make it 'Y' otherwise 'N'. The Item columns are more and or of different name(not like Item-X).
I need the query to do this. Can anyone suggest the best way to do this in SQL server? or at least point me to the right resource. Thanks in advance.

You can use case statement to do that, something like this:
case when Item1 = 'Y' or Item2 = 'Y' or Item3 = 'Y' then 'Y' else 'N' end

Since you have more column's to check you can reverse the IN operator
SELECT *,
CASE WHEN 'Y' in (Item1 , Item2 , Item3) THEN 'Y' ELSE 'N' END as BoughtAnySpecialItem
FROM Yourtable
Now you can easily list the column's in IN opertaor

Related

Using sql to recursively generate values depending on keys and column values

I have a table like this:
store
item
value
store1
item1
2
store1
item2
3
I want to use it to create the following table:
store
item
value
store1
item1
0
store1
item1
1
store1
item1
2
store1
item2
0
store1
item2
1
store1
item2
2
store1
item2
3
I'm aware that I can do with recursive n(n) as (select 0 n union all select n + 1 from n limit 40) and then later a cross join if the upper limit was constant (40) but in my case, it changes by (store, item). I was wondering if this can be done in SQL or if it is better to figure it out in python. Thanks.
You can use a recursive CTE. The syntax is something like this:
with recursive cte(store, item, value, n) as (
select store, item, value, 0
from t
union all
select store, item, value, n + 1
from cte
where n < value
)
select store, item, n as value
from cte;
The exact syntax for recursive CTEs varies, depending on the database. This appears to be similar to the code you have in your question.
Here is a db<>fiddle.

How to get total record count for records that match 3 different criteria in single query

I have a table similar to this
Item1 Item2
yes yes
yes no
yes yes
yes yes
etc., etc.
I need to get the count of the records that have both Item1 & Item2. And also the counts for records that just have Item1 or Item2 and not have duplicate records in the final query. Any suggestions will be greatly appreciated as always.
Perhaps you just want group by:
select item1, item2, count(*)
from t
group by item1, item2;
If you specifically want to combine values, you could do:
select sum(case when item1 = 'yes' and item2 = 'yes' then 1 else 0 end) as two_yesses,
sum(case when (item1 = 'yes' or item2 = 'yes') and item1 <> item2
then 1 else 0
end) as one_yes
from t;

One column condition in sql

I have a table:
[letter] [Name] [status] [price]
A row1 1 11
A row1 1 15
B row2 2 9
B row2 3 23
B row2 3 30
And want to select data something like this:
SELECT letter, Name,
COUNT(*),
CASE WHEN price>10 THEN COUNT(*) ELSE NULL END
GROUP BY letter, Name
the result is:
A row1 2 2
B row2 1 null
B row2 2 2
But I want this format:
A row1 2 2
B row2 3 2
Please, help me to modify my query
Close. Probably want this instead:
SELECT letter, Name,
COUNT(*),
SUM(CASE WHEN price>10 THEN 1 ELSE 0 END)
FROM TableThatShouldHaveAppearedInTheQuestionInTheFromClause
GROUP BY letter, Name
should work. Assuming that the intention of the fourth column is to return the count of the number of rows, within each group, with a price greater than 10. It's also possible to do this as a COUNT() over a CASE then returns non-NULL and NULL results for the rows that should and should not be counted, but I find the above form easier to quickly reason about.
Since nulls are not used in aggregate functions:
SELECT letter
, name
, count(*)
, count(
case when price > 10 then 1
end
)
FROM t
GROUP BY letter, name
You were very close.
Looking to the other answers, probably this is not the best way, but it will work.
The count of the prices over 10 is made with a subquery which has a condition on price > 10 and which is joined to the current TAB record with the alias A for the same letter and name.
SELECT letter,
Name,
COUNT(*),
(SELECT COUNT(*) FROM TAB WHERE letter = A.letter and Name = A.Name WHERE price>10)
FROM TAB A
GROUP BY letter, Name

creating 2 columns from 1 main column in the same table

SELECT TOP 1000 [Value]
FROM [OnlineQnres].[dbo].[tmp_DataSets]
WHERE [VariableID] in ('1')
UNION ALL
SELECT TOP 1000 [Value]
FROM [OnlineQnres].[dbo].[tmp_oDataSets]
WHERE [VariableID] in ('4')
Providing a more updated Detail
Hi All, I have this select query above using UNION ALL. There is a column called Value and VariableID in tmp_datasets table. I need to create 2 separate columns and name them val1 for variableID is 1 and val2 if variableID is 4. If i use UNION ALL it works it creates 2000 records with the first 1000 as val1 records and next 1000 as val2 records but does not separate out into 2 sep columns. How do i separate this value column in 2 separate columns as stated above.
I have 2 columns
VALUE which has values TEST56,TEST57,230,245
VARIABLEID = 1 and 4
TEST56 AND TEST57 comes under variableid == 1
230 and 245 comes under variableid == 4
So based on this above example, I want to create a view where I have 2 columns called val1 if variableid == 1 and val2 if variable id == 4.
So it should look something like this
val1 = should show test56 and test57
val2 = should show 230 and 245
Thanks in advance
A couple case statements should do what I think you want:
SELECT TOP 1000
[Variable]
CASE [VariableID]
WHEN 1 THEN 1
ELSE 0
END AS Val1,
CASE [VariableID]
WHEN 4 THEN 1
ELSE 0
END AS Val2
FROM [OnlineQnres].[dbo].[tmp_DataSets]
WHERE [VariableID] = 1 or [VariableID] = 4
SQLFiddle link: http://sqlfiddle.com/#!6/825f2/8/0

reclassify fields in one column of a table depending on criteria

I have the following table:
person drug
------ -----
1 Y
2 Y
2 other
3 X
4 X
5 X
5 other
6 other
7 Z
However, if there is a person where they have a drug x,y,z (it will only be one distinct choice) plus 'other' - then I want to remove the row that contains other
This would mean that someone with an 'X' and 'other' would remove the row conatining 'other', but anyone with only 'other' will stay as 'other'. i.e.
person drug
------ -----
1 Y
2 Y
3 X
4 X
5 X
6 other
7 Z
where person 6 only has other, so stays that way, but persons 2 and 5 have the 'other' rows removed because they have other drug choices (x,y or z).
Thanks very much for any help.
It is unclear whether you want this removed in the results of a query or in the data itself. To return results without this row from a query, which can be written like this:
select t.*
from t
where not (t.drug = 'other' and
exists (select 1 from t t2 where t2.person = t.person and t2.drug = 'x')
)
To handle any of 'x', 'y', or 'z', change the last statement to t2.drug in ('x', 'y', 'z').