SQL query for counting sets of values - sql

Added more information to clear up some confusions. Thanks.
I am trying to group sets of values in SQL. I have the following table and trying to somehow get the results as shown in the following table. I have explored group sets in SQL 2008, cubes, basic group by clauses, but I am not able to figure out the SQL query. Can someone please help. You can change the end resultant table format if you want but the basic idea is about how to count similar sets of values. In this table a,b,c exists 2 times so the count is 2 and x,y exists 3 times so the count is 3 and x, y, z exists 1 time so the count is 1. Please help.
UserId ProductId
1 a
1 b
1 c
2 x
2 y
3 x
3 y
4 x
4 y
5 a
5 b
5 c
6 x
6 y
6 z
ProductId Count
a 2
b 2
c 2
x 3
y 3
x 1
y 1
z 1

SELECT COUNT(`ProductId`),`ProductId ` WHERE 1 GROUP BY `ProductId` ORDER BY `ProductId` ASC

SELECT ProductId, COUNT(UserId) AS NbrOfUsers
FROM TABLE_NAME
GROUP BY ProductId, COUNT(UserId)
You're selecting ProductId & the count of how many UserId exist for that ProductId.
GROUP BY ProductId will group your counted UserId based on ProductId and also display the count as NbrOfUsers.
Your output will look like this:
ProductId NbrOfUsers
a 2
b 2
c 2
x 3
y 3

Related

Merge row values based on other column value

I'm trying to merge the values of two rows based on the value of another row in a different column. Below is my based table
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3
100
1
C
4
100
1
D
5
20
1
Here is the SQL query I used
select customer_id, property_id, bookings_per_customer, cancellations_per_customer
from table
And this is what I want to see. Any ideas the query to get this would be? We use presto SQL
Thanks!
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3 , 4
100
1
D
5
20
1
We can try:
SELECT
customer_id,
ARRAY_JOIN(ARRAY_AGG(property_id), ',') AS properties,
bookings_per_customer,
cancellations_per_customer
FROM yourTable
GROUP BY
customer_id,
bookings_per_customer,
cancellations_per_customer;

Finding adjacent column values from the last non-null value of a certain column in Snowflake (SQL) using partition by

Say I have the following table:
ID
T
R
1
2
1
3
Y
1
4
1
5
1
6
Y
1
7
I would like to add a column which equals the value from column T based on the last non-null value from column R. This means the following:
ID
T
R
GOAL
1
2
1
3
Y
1
4
Y
3
1
5
4
1
6
Y
4
1
7
6
I do have many ID's so I need to make use of the OVER (PARTITION BY ...) clause. Also, if possible, I would like to use a single statement, like
SELECT *
, GOAL
FROM TABLE
So without any extra select statement.
T is in ascending order so just null it out according to R and take the maximum looking backward.
select *,
max(case when R is not null then T end)
over (
partition by id
order by T
rows between unbounded preceding and 1 preceding
) as GOAL
from TBL
http://sqlfiddle.com/#!18/c927a5/5

Create multiple rows based on 1 column

I currently have a table with a quantity in it.
ID Code Quantity
1 A 1
2 B 3
3 C 2
4 D 1
Is there anyway to write a sql statement that would get me
ID Code Quantity
1 A 1
2 B 1
2 B 1
2 B 1
3 C 1
3 C 1
4 D 1
I need to break out the quantity and have that many number of rows
Thanks
Here's one option using a numbers table to join to:
with numberstable as (
select 1 AS Number
union all
select Number + 1 from numberstable where Number<100
)
select t.id, t.code, 1
from yourtable t
join numberstable n on t.quantity >= n.number
order by t.id
Online Demo
Please note, depending on which database you are using, this may not be the correct approach to creating the numbers table. This works in most databases supporting common table expressions. But the key to the answer is the join and the on criteria.
One way would be to generate an array with X elements (where X is the quantity). So for rows
ID Code Quantity
1 A 1
2 B 3
3 C 2
you would get
ID Code Quantity ArrayVar
1 A 1 [1]
2 B 3 [1,2,3]
3 C 2 [2]
using a sequence function (e.g, in PrestoDB, sequence(start, stop) -> array(bigint))
Then, unnest the array, so for each ID, you get a X rows, and set the quantity to 1. Not sure what SQL distribution you're using, but this should work!
You can use connect by statement to cross join tables in order to get your desired output.
check my solution it works pretty robust.
select
"ID",
"Code",
1 QUANTITY
from Table1, table(cast(multiset
(select level from dual
connect by level <= Table1."Quantity") as sys.OdciNumberList));

PLSQL or SSRS, How to select having all values in a group?

I have a table like this.
ID NAME VALUE
______________
1 A X
2 A Y
3 A Z
4 B X
5 B Y
6 C X
7 C Z
8 D Z
9 E X
And the query:
SELECT * FROM TABLE1 T WHERE T.VALUE IN (X,Z)
This query gives me
ID NAME VALUE
______________
1 A X
3 A Z
4 B X
6 C X
7 C Z
8 D Z
9 E X
But i want to see all values of names which have all params. So, only A and C have both X and Z values, and my desired result is:
ID NAME VALUE
______________
1 A X
2 A Y
3 A Z
6 C X
7 C Z
How can I get the desired result? No matter with sql or with reporting service. Maybe "GROUP BY ..... HAVING" clause will help, but I'm not sure.
By the way I dont know how many params will be in the list.
I realy appreciate any help.
The standard approach would be something like
SELECT id, name, value
FROM table1 a
WHERE name IN (SELECT name
FROM table1 b
WHERE b.value in (x,y)
GROUP BY name
HAVING COUNT(distinct value) = 2)
That would require that you determine how many values are in the list so that you can use a 2 in the HAVING clause if there are 2 elements, a 5 if there are 5 elements, etc. You could also use analytic functions
SELECT id, name, value
FROM (SELECT id,
name,
value,
count(distinct value) over (partition by name) cnt
FROM table1 t1
WHERE t1.value in (x,y))
WHERE cnt = 2
I prefer to structure these "sets within sets" of queries as an aggregatino. I find this is the most flexible approach:
select t.*
from t
where t.name in (select name
from t
group by name
having sum(case when value = 'X' then 1 else 0 end) > 0 and
sum9case when value = 'Y' then 1 else 0 end) > 0
)
The subquery for the in finds all names that have at least one X value and one Y value. Using the same logic, it is easy to adjust for other conditions (X and Y and Z,; X and Y but not Z and so on). The outer query just returns all the rows instead of the names.

How to find recursively self-joined records from a table

I've got a simple problem that really has me stumped.
I have a master table Table X
Table X
ID
_________
1
2
3
4
5
I have a join table for Table X that allows records to be self joined. Let's call this JoinTableX
JoinTableX
RecordAID RecordBID
--------- --------
1 2 (So Record 1 from Table X has a link to Record 2 from Table X)
1 3
1 4
2 3
2 4
3 1
3 2
4 1
4 2
So how do I write a SQL query to show me all the records in JoinTableX that have a duplicate dependency on each other (example bove Table X Record 1 is linked to Table X Record 4 and Table X Record 4 is linked to Table X Record 1.
select *
from JoinTableX a
inner join JoinTableX b on a.RecordAID = b.RecordBID
and a.RecordBID = b.RecordAID
(SELECT RecordAID, RecordBID FROM JoinTableX)
INTERSECT
(SELECT RecordBID, RecordAID FROM JoinTableX)