Retrieve combinations from different rows as inputs SQL - sql

I am new to SQL and I am kind of stuck at an issue. I have a table with following structure... The table format is something that I cannot change. I have tried INNER joins and cross join but that did not help me much.
I have to retrieve all the records which depends on my input for example if my input will be Chicago, Sedan and chilly.
I should retrieve only combination of Chicago or Sedan or Chilly or Chicago and Sedan or Chicago and chilly and so on... for example in the following table ID 4 should not be retrieved as it is combination of new york and chilly.
Any help would be greatly appreciated.
ID TYPE CODE
1 CITY Chicago
1 CAR SEDAN
1 WEATHER CHILLY
2 WEATHER CHILLY
2 CAR SEDAN
3 CITY Chicago
4 CITY New York
4 CAR SEDAN

Sai,
You can give this a try to see if this is what you are after.
I did add one more line to your original example table just to help illustrate how this SQL would render.
ID TYPE CODE
1 CITY Chicago
1 CITY Dallas
1 CAR SEDAN
1 WEATHER CHILLY
2 WEATHER CHILLY
2 CAR SEDAN
3 CITY Chicago
4 CITY New York
4 CAR SEDAN
Using this SQL will render your table output is a more manageable format.
SELECT * FROM
((select id, type, code from TABLE1 t1)
pivot (listagg(code,',') within group (order by type)
for type in('CITY' as CITY,'CAR' as CAR, 'WEATHER' as WEATHER)))
order by id
This will turn the table format above to the following formatted record set.
ID CITY CAR WEATHER
1 Chicago,Dallas SEDAN CHILLY
2 (null) SEDAN CHILLY
3 Chicago (null) (null)
4 New York SEDAN (null)
Of course, if you wish to place quotes around each item in the output you could do this.
SELECT * FROM
((select id, type, code from TABLE1 t1)
pivot (listagg(''''||code||'''',',') within group (order by type)
for type in('CITY' as CITY,'CAR' as CAR, 'WEATHER' as WEATHER)))
order by id
This would then render as
ID CITY CAR WEATHER
1 'Chicago','Dallas' 'SEDAN' 'CHILLY'
2 (null) 'SEDAN' 'CHILLY'
3 'Chicago' (null) (null)
4 'New York' 'SEDAN' (null)
Is this more to what you are looking for?

Slight extension of Gordon's query
http://sqlfiddle.com/#!4/b844db/13
SELECT * FROM TABLE1 t1
WHERE t1.ID IN
(SELECT ID
FROM TABLE1 t2
GROUP BY ID
HAVING
SUM(CASE WHEN CODE IN ('Chicago','SEDAN','CHILLY')
THEN 1 ELSE 0 END)
= COUNT(*)
)

You can use group by and having:
select id
from t
group by id
having sum(case when code in ('Chicago', 'Sedan', 'chilly') then 1 else 0 end) = count(*);
Perhaps you intend:
having sum(case when type = 'City' and code <> 'Chicago' then 1 else 0 end) = 0 and
sum(case when type = 'Car' and code <> 'Sedan' then 1 else 0 end) = 0 and
sum(case when type = 'Weather' and code <> 'Chilly' then 1 else 0 end) = 0

Related

One to many relationship, find groups that contain only the specified values

So lets say I have a table
ID Car
1 Polo
2 Jetta
And a one-many relationship like
Id Driver Car
1 Jason 1
2 Fred 1
2 Fred 2
3 Batman 1
4 Frodo 2
How can I get records from car that Only has Fred and Frodo driving it?
I.e. the query needs to return only car 2.
Assuming that only has Fred and Frodo driving it means Fred, Frodo and no other, you would write:
SELECT car
FROM car_driver
GROUP BY car
HAVING COUNT(CASE WHEN driver IN ('Fred', 'Frodo') THEN 1 END) = 2
AND COUNT(*) = 2
You can use the set operator INTERSECT:
SELECT car FROM drivers WHERE driver = 'Fred'
INTERSECT
SELECT car FROM drivers WHERE driver = 'Frodo'
db<>fiddle
maybe something like this
select c.car
from cardriver cd join cars c
on c.id=cd.car and cd.Driver in ('Fred','Frodo')
group by c.car
having count(distinct cd.Driver)=2
db fiddle here

Count results that have different column value related to same ID

I'm new to SQL and looking for help on how to best do this.
I have 2 tables with the following columns:
Investors: Round ID, Investor Name, Investor City, Investor Country
Rounds: Round ID, Company Name, Company City, Company Country
I joined them to get this result
Round ID
Investor Country
Company Country
1
US
Spain
1
UK
Spain
1
Spain
Spain
2
France
Germany
2
UK
Germany
3
UK
Italy
3
Italy
Italy
I will need to get the number of investors (per round ID) which have their country different from the Company Country, So like for Round 1 I will have 2, for Round 2 it's 0 and for round 3 it's 1.
How could I do this?
Thank you for your help!
Just use conditional aggregation:
select round,
sum(case when investor_country <> company_company then 1 else 0 end) as cnt
from t
group by round;
Looking at your expected output, I think you need the count = 0 in case there do not exists a single record for investor country = company country and if there is, then you need all other record count.
You can use conditions as follows:
select round_id,
case when count(case when investor_country = company_company then 1 end) = 0
then 0
else count(case when investor_country <> company_company then 1 end)
end as cnt
from your_table t
group by round_id;
If you need diffrent counts:
SELECT
RoundId,
SUM(IIF(InvestorCountry != CompanyCountry,1,0)) AS Count
FROM
YOUR_TABLE_OR_VIEW
GROUP BY
RoundId
If you need difrent count and when all result of a same Round are difrent you want zero:
SELECT
t.RoundId,
IIF(t.Count = t.DiffrentCount,0,t.DiffrentCount) 'Count'
FROM
(
SELECT
RoundId,
SUM(1) AS 'Count',
SUM(IIF(InvestorCountry != CompanyCountry,1,0)) AS 'DiffrentCount',
FROM
YOUR_TABLE_OR_VIEW
GROUP BY
RoundId
)t

SQL query to get only rows match the condition based on two separated columns under one 'group by'

The simple SELECT query would return the data as below:
Select ID, User, Country, TimeLogged from Data
ID User Country TimeLogged
1 Samantha SCO 10
1 John UK 5
1 Andrew NZL 15
2 John UK 20
3 Mark UK 10
3 Mark UK 20
3 Steven UK 10
3 Andrew NZL 15
3 Sharon IRL 5
4 Andrew NZL 25
4 Michael AUS 5
5 Jessica USA 30
I would like to return a sum of time logged for each user grouped by ID
But for only ID numbers where both of these values Country = UK and User = Andrew are included within their rows.
So the output in the above example would be
ID User Country TimeLogged
1 John UK 5
1 Andrew NZL 15
3 Mark UK 30
3 Steven UK 10
3 Andrew NZL 15
First you need to identify which IDs you're going to be returning
SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew';
and based on that, you can then filter to aggregate the expected rows.
SELECT ID,
[User],
Country,
SUM(Timelogged) as Timelogged
FROM mytable
WHERE (Country='UK' OR [User]='Andrew')
AND ID IN( SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew')
GROUP BY ID, [User], country;
So, you have described what you need to write almost perfectly but not quite. Your result table indicates that you want Country = UK OR User = Andrew, rather than AND
You need to select and group by, then include a WHERE:-
Select ID, User, Country, SUM(Timelogged) as Timelogged from mytable
WHERE Country='UK' OR User='Andrew'
Group by ID, user, country

Combine rows into one result and add results as different values in SQL

I have a table (people) that include the following information:
id cert_id type name
1 123 owner Paul
2 123 seller George
3 123 buyer steve
4 456 owner micheal
I also have a table (items) that includes the following:
id cert_id item_name
1 123 staples
2 123 cheese
3 123 iguanas
4 456 pie
Basically, what I want to do is have the results as the following:
cert_id owner_name seller_name buyer_name item_name
123 Paul George steve staples, cheese, iquanas
456 micheal pie
So far I have been able to use MAX(CASE WHEN people.type='owner' THEN people.name END) AS owner_name, but I cannot get the seller name to append to the other row ('im not sure if this is even possible via the SQL statement or if I should do some formatting with the results afterwards. Any advice on combining rows would be helpful, or a simple "not possible" would let me know what the limitations are.
Thanks in advance!
You should be able to use the following query to get the result:
select p.cert_id,
max(case when p.type = 'owner' then p.name end) owner_name,
max(case when p.type = 'seller' then p.name end) seller_name,
max(case when p.type = 'buyer' then p.name end) buyer_name,
array_agg(distinct i.item_name) Items
from people p
inner join items i
on p.cert_id = i.cert_id
group by p.cert_id;
See SQL Fiddle with Demo
This can be accomplished using INNER JOIN or LEFT-OUTER-JOIN...

T-SQl Query Problem

I have a table called CorporateTree and Production and the tables have data like:
Table: CorporateTree
DivisionName RegionName CommonName BU
Central Region 1 Raintree 101
Central Region 1 Glenwood 102
East Region 2 Balsa 201
East Region2 Warren 202
Table: Production
ProdID BU ResidentName ResidentID Room
1 101 Smith, Jeff 234859 1002-A
2 202 Mill, Steve 125467 2002-B
3 101 Sisk, Paul 4383943 1009-C
4 101 Sims, Gary 384393 1010-A
5 202 Mason, Sam 32902 1012-A
I am looking to get output like this:
Division Region Facility Business Unit ResidentCount Status
Central Region 1 Glenwood 102 0 Flag
Central Region 1 Raintree 101 3
East Region 2 Balsa 201 0 Flag
East Region 2 Warren 202 2
if the Number of Residents is zero (0) output the value of “Flag” in a Status
i tried this query:
SELECT ct.DivisionName,ct.RegionName,ct.CommonName AS Facility,ct.BU AS [Business Unit],
(SELECT ROW_NUMBER() OVER (PARTITION BY p.BU ORDER BY p.BU DESC)) AS ResidentCount FROM
CorporateTree ct INNER JOIN Production p ON
p.Bu = ct.BU
But it doesn't seem to be working? Can any one help me on this?
You'll want to use a LEFT JOIN to account for any Business Units that have no rows in the Production table.
SELECT ct.DivisionName, ct.RegionName, ct.CommonName AS Facility, ct.BU AS [Business Unit],
COUNT(p.BU) as ResidentCount,
CASE WHEN COUNT(p.BU) = 0 THEN 'Flag' ELSE '' END AS Status
FROM CorporateTree ct
LEFT JOIN Production p
ON p.BU = ct.BU
GROUP BY ct.DivisionName, ct.RegionName, ct.CommonName, ct.BU