How to combine rows using a CASE Statement - sqlite

I have a database with 58 customers(58 rows) with a column(country). How do I group up all the rows where a country only appears once and change its name to "Other" using a CASE Statement
SELECT
CASE
WHEN (SELECT COUNT(country) FROM customer GROUP BY country)=1 THEN 'Other'
ELSE country
END country
FROM customer
The problem is that when I run my query, all the countries become Other. I only want the countries that appear once to be called Other.

Here's how to do it.
SELECT
CASE WHEN COUNT(country) = 1 THEN 'Other' ELSE country END
FROM customer
GROUP BY country;

To update the actual table:
WITH map AS
(SELECT country,
CASE WHEN COUNT(country) = 1 THEN 'Other'
ELSE country END mapped
FROM customer
GROUP BY country)
UPDATE customer
SET country = (SELECT mapped FROM map WHERE map.country = customer.country);

With a subquery that counts how many times a country appears in the table:
SELECT
CASE
WHEN (SELECT COUNT(*) FROM customer WHERE country = c.country) = 1 THEN 'Other'
ELSE c.country
END country
FROM customer c
Or with a join of the table to the subquery that returns all the counter of all the countries:
SELECT
CASE
WHEN g.counter = 1 THEN 'Other'
ELSE c.country
END country
FROM customer c INNER JOIN (
SELECT country, COUNT(*) counter
FROM customer
GROUP BY country
) g ON g.country = c.country
If you want your table grouped by the result of this CASE statement use an alias to distinguish from the table's column country:
SELECT
CASE
WHEN (SELECT COUNT(*) FROM customer WHERE country = c.country) = 1 THEN 'Other'
ELSE c.country
END _country
FROM customer c
GROUP BY _country

Related

UNION not working Teradata SQL. Syntax error: Top N option is not allowed in a query connected by set operators

When I run both queries individually, they run correctly. But when I try to combine both result sets into one table using the UNION operator, it doesn't run and I get the error message : "Syntax error: Top N option is not allowed in a query connected by set operators."
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Edtech'
group by city
order by 2 desc
union
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Internet software & services'
group by city
order by 2 desc
I would appreciate any help,
Thanks.
Instead you can use window functions to achieve the same:
select
city,
count(*) ccount
from unicorns
where city is not null and industry = 'Edtech'
group by city
QUALIFY ROW_NUMBER() OVER (ORDER BY ccount DESC) = 1
union
select
city,
count(*) ccount
from unicorns
where city is not null and industry = 'Internet software & services'
group by city
QUALIFY ROW_NUMBER() OVER (ORDER BY ccount DESC) = 1
This way you aren't relying on ordering/top an interim result set (outside of partition ordering) and Teradata will be ok with it.
It's probably because the optimizer doesn't know if the 2nd ORDER BY is part of the top or the final ORDER BY of the UNION.
The common workaround for this type of error is to wrap the Selects in Derived Tables/CTEs:
select *
from
(
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Edtech'
group by city
order by 2 desc
) as dt
union
select *
from
(
select
top 1
city,
count(*)
from unicorns
where city is not null and industry = 'Internet software & services'
group by city
order by 2 desc
) as dt

How do I include all max values within a row?

I'm very new to learning SQL, I apologize if my question isn't completely accurate.
The question I'm trying to answer with this query is "What is the most popular music genre in each country?" I've had to use a subquery and it works, but I found that for a few countries in the table, more than one genre has the MAX value. I'm stuck with how to edit my query so that all genres with the max value show in the results. Here is my code, using DB Browser for SQLite:
SELECT BillingCountry AS Country , name AS Genre , MAX(genre_count) AS Purchases
FROM (
SELECT i.BillingCountry, g.name, COUNT(g.genreid) AS genre_count
FROM Invoice i
JOIN InvoiceLine il
ON il.InvoiceId = i.InvoiceId
JOIN TRACK t
ON il.trackid = t.TrackId
JOIN Genre g
ON t.genreid = g.GenreId
GROUP BY 1,2
) sub
GROUP BY 1
Here is an example of the result:
| Country | Genre |Purchase|
|---------|-------|--------|
|Agrentina| Punk | 9 |
|Australia| Rock | 22 |
BUT in running just the subquery to COUNT the purchases, Argentina has two Genres with 9 Purchases (the max number for that country). How do I adjust my query to include both and not just the first one in the row?
You can do it with RANK() window function:
SELECT BillingCountry, name, genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
This will return the ties in separate rows.
If you want 1 row for each country, you could also use GROUP_CONCAT():
SELECT BillingCountry, GROUP_CONCAT(name) AS name, MAX(genre_count) AS genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
GROUP BY BillingCountry

executing multiple select statements to pick a value in where condition using Case statement

Case statement with select statement as loops in where condition
need to bring values by referring two tables. if the value doesn't exist in table a it has to refer the 2nd table
Sel * from Table A
where city = (case when (sel distinct city from Table A) is null
then (sel city from Table B) end)
expected output is as shown below
Sel * from Table A
where City = 'XYZ'
if value is not present in table A it has to refer Table B statement and show the value in where condition
The one thing you need to be careful with here is to make sure you return a single value in your scalar sub-queries -- (sel distinct city from Table A) and (sel city from Table B). If you can always guarantee that then I think your query will work as is.
A safer way to do it is guarantee you always get one row. Here's one option:
SELECT *
FROM TableA
WHERE City = (
SELECT city
FROM (
-- Get all cities from TableA
SELECT city, 1 AS table_priority
FROM tableA
UNION ALL
-- Get all cities from TableB
SELECT city, 2
FROM tableB
) src
QUALIFY ROW_NUMBER() OVER(ORDER BY src.table_priority, src.city) = 1 -- Return one row
)

How to use case statement with select and group by

select company,
case when ((select count() from ftmuser where active='0' group by company)>5) Then (select count() from ftmuser where active='0' group by company)
ELSE '0'
END
From ftmuser
I want to display only those records having count > 5 but above query fails and says ERROR: more than one row returned by a subquery used as an expression
SQL state: 21000
Please guide me on this.
Thanks.
Try this:
select company, case when ((select count(*) from ftmuser where active='0'
group by company where company=ft.company)>5)
Then (select count() from ftmuser <br>where active='0'
group by company where company=ft.company )
ELSE '0' END
From ftmuser ft

query string error in asp.net

I have a problem in query.
Error is: {"Invalid column name 'TotalRecords'."}
I have a table named upload_news in this table there many records and I want retrieve data by country wise where in the distinct countries greater than 20 records.
select count(Distinct country) AS TotalRecords, country from upload_news where TotalRecords > 20";
You need to use Group By and Having:
select count(Distinct country) AS TotalRecords, country from upload_news
group by country
having count(Distinct country) > 20
Try like this
"SELECT *
FROM
(
select count(Distinct country) AS TotalRecords, country from upload_news
group by country
) T
where TotalRecords > 20";
because TotalRecords alias column, you can't access it directly.

Resources