SQL aggregation to add new column with flag - sql

I have a column with
Country
-------
Canada
India
USA
India
China
Canada
I want to update this table by inserting another column called M_U which can only have 0 or 1
If country occurs more than once = 1
If country occurs only once = 0
output
-------
Canada 1
India 1
USA 0
India 1
China 0
Canada 1

This should work for you:
select a.country, case when b.c >1 then 1 else 0 end
from countries a
join (
select Country, count(*) as c from countries group by Country
) b on b.country = a.country

You should use windows functions for this:
select t.*,
(case when count(*) over (partition by country) > 1 then 1 else 0 end) as flag
from t;
This is essential a_horse_with_no_name's answer. I'll delete it if that answer is undeleted.

Related

SQL fill in redundant values to table

I want to take the following table...
City
Company
Revenue
New York
A
400
New York
B
300
Singapore
B
400
Washington D.C.
C
400
London
D
400
and produce the below version.
City
Company
Present
Revenue
New York
A
1
400
New York
B
1
300
New York
C
0
0
New York
D
0
0
Singapore
A
0
0
Singapore
B
1
400
Singapore
C
0
0
Singapore
D
0
0
...
...
London
D
1
400
So, basically filling extra company values to encompass the entire dataset, adding a 1 in the "Present" field if they are present, otherwise zero...
I hope my question makes sense!
You can pull this off by first making a result set that has every combination of company and city. A cross join will do the trick here:
SELECT companies.company, cities.city
FROM (SELECT DISTINCT Company FROM yourtable) companies,
(SELECT DISTINCT City FROM yourtable) cities
We can now LEFT JOIN from that result set into your table to get to the final result set:
WITH all_values AS
(
SELECT companies.company, cities.city
FROM (SELECT DISTINCT Company FROM yourtable) companies,
(SELECT DISTINCT City FROM yourtable) cities
)
SELECT all_values.company,
all_values.city,
CASE WHEN yourtable.company IS NOT NULL THEN 1 ELSE 0 END as Present,
yourtable.Revenue
FROM
all_values
LEFT OUTER JOIN yourtable
ON all_values.company = yourtable.company
AND all_values.city = yourtable.city;
select city.city
, company.company
, coalesce(t.Revenue, 0)
, case when t.revenue is not null then 1 else 0 end as Present
from (select distinct company from tablename) company
cross join (select distinct City from tablename) city
left join tablename t
on t.city = city.city
and t.company = company.company

PostreSQL filter results by subset of a joined table and group them

I have table of people, another table of cars and a third table to join them since they have a many to many relationship. I want to select people who own a certain set of cars and group them by a region property on the person. So for example I would want to find all American's who own a Honda and a Nissan.
Example:
people table
id name region
1 Jon America
2 Jane Europe
3 Mike America
cars table
id make
1 Honda
2 Toyota
3 Nissan
people_cars table
person_id car_id
1 1
1 3
2 2
3 1
Desired result:
region own_honda_and_nissan
America 1
Europe 0
An idea for a SQL expression I have is:
SELECT
people.region,
CASE WHEN SUM(CASE WHEN cars.name IN ('Honda', 'Nissan') THEN 1 ELSE 0 END) = 2 THEN 1 ELSE 0 AS own_honda_and_nissan
FROM people
JOIN people_cars ON people_cars.person_id = people.id
JOIN cars ON people_cars.car_id = cars.id
GROUP BY people.region
HAVING
SUM(CASE WHEN cars.name IN ('Honda', 'Nissan') THEN 1 ELSE 0 END) = 2
ORDER BY own_honda_and_nissan DESC
This works if you group by people.id but once they get grouped by region it no longer works.
Use two levels of aggregation:
SELECT p.pregion, COUNT(*) as own_honda_and_nissan
FROM (SELECT pid, p.region,
FROM people p JOIN
people_cars pc
ON pc.person_id = p.id JOIN
cars c
ON pc.car_id = c.id
WHERE c.name IN ('Honda', 'Nissan')
GROUP BY p.id, p.region
HAVING COUNT(DISTINCT c.name) = 2
) p
GROUP BY p.region
ORDER BY own_honda_and_nissan DESC

How to convert each row of the first column as a header and second as a row?

I want a SQL query that convert each rows of the first column as a header and second columns as a row so how can we do that using SQL.. below is a example:
In my table records like
FieldName Value link
-----------------------------
Country India 1
Country USA 2
Country Russia 3
Amount 10000 1
Amount 20000 2
Amount 30000 3
Result should be :
Country Amount
---------------
India 10000
USA 20000
Russia 30000
please let me know if anyone have an idea.
Thanks in advance.
You can use (demo)
SELECT MAX(CASE WHEN FieldName = 'Country' THEN Value END) AS Country,
MAX(CASE WHEN FieldName = 'Amount' THEN Value END) AS Amount
FROM YourTable
GROUP BY link
Or
select a.Value, b.Value
from (select Fieldname, Value, link from theTable) as a
inner join (select Fieldname, Value, link from theTable) as b on a.link = b.link
where
a.FieldName > b.FieldName;

SQL Query For These Two Tables

I have these two tables:
Person
Name Gender RegionID
Bob Male 1
Mary Female 2
Jane Female 3
Chris Male 1
Paul Male 2
Matt Male 2
Jenny Female 1
Region
ID Region
1 North
2 South
3 Central
I would like to end up with a table like this:
Region Male Female
North 2 1
South 2 1
Central 0 1
I first tried to get the resulting table with the region's ID in there so no join required:
select RegionID, Gender, count(Name) from Person group by RegionID
But the Gender field is coming back undefined. And didn't really know where to go from there.
As tagged, I'm using the alasql JavaScript library.
Try to look at this:
SELECT A.Region
, SUM(CASE WHEN Gender = 'Male' Then 1 else 0 end) Male
, SUM(CASE WHEN Gender = 'Female' Then 1 else 0 end) Female
FROM Region A
Inner Join Person B
On A.ID = B.RegionID
Group By A.Region
You can use this
select region
,sum(case when b.Gender='Male' then 1 else 0 end) Male
,sum(case when b.Gender='Female' then 1 else 0 end) Female
from Region a
inner join Person b on a.[Id]=b.RegionID
group by a.[Id],a.Region
order by [id]
In tsql you can pivot, which might be easier if you have more than a couple of values to pivot on:
Select * from
( select Region ,Gender
from Region a
inner join Person b on a.[Id]=b.RegionID ) p
pivot
( count(Gender)
for Gender
IN ([Male],[Female])
) pivottable
If you add a third gender, nonbinary like this
insert into Person values ('Kim','Nonbinary',3)
You can easily extend you query to account for that:
Select * from
( select Region ,Gender
from Region a
inner join Person b on a.[Id]=b.RegionID ) p
pivot
( count(Gender)
for Gender
IN ([Male],[Female],[Nonbinary])
) pivottable
order by a.[id]
For anyone looking for the final solution in alasql, this is what I came up with thanks to the help from this page:
var res = alasql("SELECT regionData.Title \
, SUM(CASE WHEN peopleData.Gender = 'Male' THEN 1 ELSE 0 END) AS Male \
, SUM(CASE WHEN peopleData.Gender = 'Female' THEN 1 ELSE 0 END) AS Female \
FROM ? regionData LEFT JOIN ? peopleData \
ON regionData.ID = peopleData.RegionID\
GROUP BY regionData.Title", [regionData, bensData]);

SQL programming

Given the two tables below, write a select statement that will select all the country names that don't have exactly one default language.
Table A
id country_code country_name
1 CAN Canada
2 USA United States of America
3 MEX Mexico
4 IND India
5 ESP Spain
Table B
id country_code language_code is_default
1 USA en t
2 CAN fr t
3 CAN en t
4 USA es f
5 USA zh f
6 IND en f
7 MEX es t
8 IND hi f
9 CHL es f
Join the tables and GROUP BY country_name. use a HAVING clause to filter the resulting rows to just those that have multiple language codes. You don't have to include the COUNT() as a column in order to use it in the HAVING clause.
select A.country_name
from TableA as A
inner join TableB as B
on A.country_code = B.country_code
where b.is_default = 't'
group by A.country_name
having count(language_code) > 1
You're going to have to use an inner join on the "Country Code" to grab the country name. Also, you're going to have to do a count of iterations of the country name to determine the number of language_code rows present. Enjoy your Group By! :D