How to query in the same table, comparing the field count? - sql

I need to query a table, in which the amount of a field should be equal to another, in the same table, for the same group.
This is my table:
ID BUYER CAR
1 1 Audi
2 1 Audi
3 1 BMW
4 1 BMW
5 2 Audi
6 2 Audi
7 2 BMW
8 2 BMW
9 2 BMW
I need to get if a buyer has bought the same amount of Audi than BMW, if not, those rows shouldn't be retrieved.
So, with this logic, the query should return all the rows for buyer 1 only , because he has bought 2 Audi and 2 BMW.
This will be the return table:
ID BUYER CAR
1 1 Audi
2 1 Audi
3 1 BMW
4 1 BMW
Hope you can help me.
This is the table:
http://sqlfiddle.com/#!3/853fa/3

Group by buyer and use the having clause to filter by BMW and Audi count. Then select all records of the buyers found.
select *
from mytable
where buyer in
(
select buyer
from mytable
group by buyer
having
sum(case when car = 'BMW' then 1 end) =
sum(case when car = 'Audi' then 1 end)
);

Related

SQL Group by Sales Rep - Select 2 counts

I would like to query a table that has leads assigned by sales rep to return the unique number of leads grouped by agent and also the number sold. There can be multiple leads from one buyer, I would like to select distinct so each buyer is counted only once. Here is the layout of the data:
AgentId
BuyerEmail
Product
Category
1
lisa#gmail.com
Jeans
1
1
lisa#gmail.com
Hat
1
1
ryan#gmail.com
Shoes
3
2
mark#gmail.com
Jeans
1
2
mark#gmail.com
Socks
1
2
mark#gmail.com
Hat
1
4
john#gmail.com
Shirt
3
5
lou#gmail.com
Hat
3
5
tim#gmail.com
Shirt
3
I would like to return a dataset like the following:
AgentId
UniqueLeads
QtySold
1
2
1
2
1
0
4
1
1
5
2
2
I can query this individually but I can't get it to return in one result set. Here are the 2 separate queries:
SELECT COUNT(DISTINCT BuyerEmail) FROM SalesLeads GROUP BY InitialAgent
SELECT COUNT(DISTINCT BuyerEmail) FROM SalesLeads WHERE Category = 3 GROUP BY InitialAgent
How can I query the table and have both data points return in one result set? Please note, a category = 3 means it is sold.
You can use conditional aggregation to calculate QtySold in the same statement:
select AgentId,
count(distinct BuyerEmail) as UniqueLeads,
count(case when Category = 3 then Category end) as QtySold
from SalesLeads
group by AgentId
When Category is anything other than 3 the case statement returns null so that record isn't counted in the QtySold calculation.
db<>fiddle

something like pivot table on postgres

I have two tables as below:
car table:
id
name
1
BMW
2
Volvo
3
Toyota
option table:
id
carid
name
value
1
1
airbag
1
2
1
seat
4
3
1
sunroof
1
4
2
airbag
0
5
2
seat
4
6
2
sunroof
1
7
3
airbag
0
8
3
seat
5
9
3
sunroof
0
how can I create the below table:
id
name
airbag
sunroof
seat
1
BMW
1
1
4
2
Volvo
0
1
4
3
Toyota
0
0
5
You may use pivoting logic here:
SELECT
c.id,
c.name,
MAX(o.value) FILTER (WHERE o.name = 'airbag') AS airbag,
MAX(o.value) FILTER (WHERE o.name = 'sunroof') AS sunroof,
MAX(o.value) FILTER (WHERE o.name = 'seat') AS seat
FROM car c
LEFT JOIN option o
ON o.carid = c.id
GROUP BY
c.id;
With the help of Postgres' support for the FILTER clause, the pivoting logic above becomes very terse and manageable.

Combine multiple instances of entry into one, differences into array

I have a table filled with cars, another table that has the car IDs and the feature IDs and another table with the feature IDs and feature names.
A car can have multiple features in that table. The result of the query is, that i get multiple instances of the same car, each having a different feature.
I would like to have only one instance of the car (by ID) and combine all features into one column (list or array). I could do it in code after the query but i would like to do it in a query instead.
Cars table Car property table Property table
ID Name Car_ID property_ID property_id Property_name
1 Audi 1 1 1 Aircon
2 BMW 1 2 2 Autopilot
3 Mercedes 2 1
3 2
Result is:
1 Audi Aircon
1 Audi Autopilot
2 BMW Autopilot
3 Mercedes None
Result should be:
1 Audi [Aircon, Autopilot]
2 BMW Autopilot
3 Mercedes None
This seems like a basic aggregation query with joins:
select c.name, group_concat(Property_name) as properties
from cars c left join
car_properties cp
on c.car_id = cp.car_id left join
properties p
on p.property_id = cp.property_id
group by c.name

Total column in a pivot example

check here for background if needed:
Pivoting a table with parametrization
We have 3 tables.
tid_color - parametrization table
--------------------------
ID ColorDescription
--------------------------
1 Green
2 Yellow
3 Red
-------------------------
tid_car - parametrization table
--------------------------
ID CARDescription
-------------------------
1 Car X
2 Car Y
3 Car Z
--------------------------
table_owners_cars
------------------------------------------------
ID CarID ColorID Owner
------------------------------------------------
1 1 1 John
2 1 2 Mary
3 1 3 Mary
4 1 3 Giovanni
5 2 2 Mary
6 3 1 Carl
7 1 1 Hawking
8 1 1 Fanny
------------------------------------------------
CarID is FOREIGN KEY to tid_car
ColorId is FOREIGN KEY to tid_color
If we code:
SELECT tcar.CarDescription, tco.ColorDescription, Count(*) as Total
FROM table_owners_cars tocar
LEFT JOIN tid_color tco ON tco.Id = tocar.ColorId
LEFT JOIN tid_Car tcar ON tcar.Id = tocar.CarId
GROUP BY CarDescription, ColorDescription
it results as:
Id CarDescription ColorDescription Total
1 CarX Green 3
2 CarX Yellow 1
3 CarX Red 1
4 CarY Yellow 1
5 CarZ Green 1
I want to pivot exactly as follows:
---------------------------------------------
Id Car Green Yellow Red Total
---------------------------------------------
1 CarX 3 1 1 5
2 CarY 0 1 0 1
3 CarZ 1 0 0 1
---------------------------------------------
Now:
we want to count the total for each row in a particular column of the table_owners_cars and this value is close to total like we see in the last column (between parenthesis). There are CarX WITH a NULL for the colorID (same can happen with the other Car) and we want to know all the number of carX, carY, CarZ (with and without (=null or 0) assigned ColorId
---------------------------------------------------
Id Car Green Yellow Red Violet Total
---------------------------------------------------
1 CarX 3 1 1 0 5 (40)
2 CarY 0 1 0 0 1 (35)
3 CarZ 1 0 0 0 1 (4)
---------------------------------------------------
DESIRED TABLE
One try with the code (very similar to one provided in the aforementioned hyperlink):
SELECT pvt.CarID, tc.Description AS Car, CONCAT (' [1] as 'Green', [2] as 'Yellow', [3] as 'Red', [1]+[2]+[3] as 'total'', '(', count(*), ')' )
FROM
(SELECT CarID, colorId
FROM table_owners_cars tocar
) p
PIVOT
(
COUNT (ColorId)
FOR ColorId IN ( [1], [2], [3])
) AS pvt
INNER JOIN tid_car tc ON pvt.CarId=tc.Id
group by p.Car
this does not work. single quotes are also a nightmare with concat. Thanks in advance.
I just find these queries easier to do with conditional aggregation:
SELECT CarId, Description,
SUM(CASE WHEN color = 'Green' THEN 1 ELSE 0 END) as Green,
SUM(CASE WHEN color = 'Yellow' THEN 1 ELSE 0 END) as Yellow,
SUM(CASE WHEN color = 'Red' THEN 1 ELSE 0 END) as Red,
SUM(CASE WHEN color IN ('Green', 'Yellow', 'Red') THEN 1 ELSE 0 END) as total_gyr,
COUNT(*) as total
FROM table_owners_cars tocar
GROUP BY CarId, Description;
I see no reason to combine the two totals into a single string column -- as opposed to having them in separate integer columns. But, you can combine them if you want.

How to insert data from one table to other table with some static data in single statement?

I've one table Car as below
Car_ID | Car_Name
Sample data
Car_ID Car_Name
1 Honda City
2 Ferrari
3 Mercedes
4 Rolls Royce
I've data in Car table. Now i've other table Car_Detail as below
Car_Detail_ID | Car_ID | Car_Color
Now i've to insert data into Car_Detail from Car where Car_Color will be default value. How to achieve this in single statement ?
Expected result
Car_Detail_ID Car_ID Color
1 1 Red
2 2 Red
3 3 Red
4 4 Red
EDIT
Sample Data
Car Table
Car_ID Car_Name
1 Honda City
2 Ferrari
3 Mercedes
4 Rolls Royce
Color Table
Color_ID Color_Name
1 Red
2 Yellow
3 Blue
4 Green
Expected Result
Car_Detail_ID Car_ID Color_ID
1 1 1
2 2 1
3 3 1
4 4 1
5 1 2
6 2 2
7 3 2
8 4 2
9 1 3
10 2 3
11 3 3
12 4 3
13 1 4
14 2 4
15 3 4
16 4 4
use INSERT INTO...SELECT statement, the query below assumes that Car_Detail_ID is an auto-incremented column and Color has a default value of Red
INSERT INTO Car_Detail (Car_ID)
SELECT Car_ID
FROM Car
but if not,
INSERT INTO Car_Detail (Car_ID, Color)
SELECT Car_ID, 'Red' Color
FROM Car
or something like this,
INSERT INTO Car_Detail (Car_Detail_ID, Car_ID, Color)
SELECT Car_ID, Car_ID, 'Red' Color
FROM Car
UPDATE 1
use CROSS JOIN
INSERT INTO CAr_Detail(Car_ID, Color_ID)
SELECT Car_ID, Color_ID
FROM Car CROSS JOIN Color
SQLFiddle Demo