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
My database structure contains columns: id, name, value, dealer. I want to retrieve row with lowest value for each dealer. I've been trying to mess up with MIN() and GROUP BY, still - no solution.
Solution1:
SELECT t1.* FROM your_table t1
JOIN (
SELECT MIN(value) AS min_value, dealer
FROM your_table
GROUP BY dealer
) AS t2 ON t1.dealer = t2.dealer AND t1.value = t2.min_value
Solution2 (recommended, much faster than solution1):
SELECT t1.* FROM your_table t1
LEFT JOIN your_table t2
ON t1.dealer = t2.dealer AND t1.value > t2.value
WHERE t2.value IS NULL
This problem is very famous, so there is a special page for this in Mysql's manual.
Check this: Rows Holding the Group-wise Maximum/Minimum of a Certain Column
select id,name,MIN(value) as pkvalue,dealer from TABLENAME
group by id,name,dealer;
here you group all rows by id,name,dealer and then you will get min value as pkvalue.
SELECT MIN(value),dealer FROM table_name GROUP BY dealer;
First you need to resolve the lowest value for each dealer, and then retrieve rows having that value for a particular dealer. I would do this that way:
SELECT a.*
FROM your_table AS a
JOIN (SELECT dealer,
Min(value) AS m
FROM your_table
GROUP BY dealer) AS b
ON ( a.dealer= b.dealer
AND a.value = b.m )
Try following:
SELECT dealer, MIN(value) as "Lowest value"
FROM value
GROUP BY dealer;
select id, name, value, dealer from yourtable where dealer
in(select min(dealer) from yourtable group by name, value)
These answers seem to miss the edge case of having multiple minimum values for a dealer and only wanting to return one row.
If you want to only want one value for each dealer you can use row_number partition - group - the table by dealer then order the data by value and id. we have to make the assumption that you will want the row with the smallest id.
SELECT ord_tbl.id,
ord_tbl.name,
ord_tbl.value,
ord_tbl.dealer
FROM (SELECT your_table.*,
ROW_NUMBER() over (PARTITION BY dealer ORDER BY value ASC, ID ASC)
FROM your_table
) AS ord_tbl
WHERE ord_tbl.ROW_NUMBER = 1;
Be careful though that value, id and dealer are indexed. If not this will do a full table scan and can get pretty slow...
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
I'm trying to use DB Browser for SQLite to construct a nested query to determine the SECOND highest priced item purchased by the top 10 spenders. The query I have to pick out the top 10 spenders is:
SELECT user_id, max(item_total), SUM (item_total + shipping_cost -
discounts_applied) AS total_spent
FROM orders AS o
WHERE payment_reject = "FALSE"
GROUP BY user_id
ORDER BY total_spent DESC
LIMIT 10
This gives the user_id, most expensive item they purchased (not counting shipping or discounts) as well as the total amount they spent on the site.
I was trying to use a nested query to generate a list of the second most expensive items they purchased, but keep getting errors. I've tried
SELECT user_id, MAX(item_total) AS second_highest
FROM orders
WHERE item_total < (SELECT user_id, SUM (item_total + shipping_cost -
discounts_applied) AS total_spent
FROM orders
WHERE payment_reject = "FALSE"
GROUP BY user_id
ORDER BY total_spent DESC
LIMIT 10)
group by user_id
I keep getting a row value misused error. Does anyone have pointers on this nested query or know of another way to find the second highest item purchased from within the group found in the first query?
Thanks!
(Note: The following assumes you're using Sqlite 3.25 or newer since it uses window functions).
This will return the second-largest item_total for each user_id without duplicates:
WITH ranked AS
(SELECT DISTINCT user_id, item_total
, dense_rank() OVER (PARTITION BY user_id ORDER BY item_total DESC) AS ranking
FROM orders)
SELECT user_id, item_total FROM ranked WHERE ranking = 2;
You can combine it with your original query with something like:
WITH ranked AS
(SELECT DISTINCT user_id, item_total
, dense_rank() OVER (PARTITION BY user_id ORDER BY item_total DESC) AS ranking
FROM orders),
totals AS
(SELECT user_id
, sum (item_total + shipping_cost - discounts_applied) AS total_spent
FROM orders
WHERE payment_reject = 0
GROUP BY user_id)
SELECT t.user_id, r.item_total, t.total_spent
FROM totals AS t
JOIN ranked AS r ON t.user_id = r.user_id
WHERE r.ranking = 2
ORDER BY t.total_spent DESC, t.user_id
LIMIT 10;
Okay, after fixing your table definition to better reflect the values being stored in it and the stated problem, and fixing the data and adding to it so you can actually get results, plus an optional but useful index like so:
CREATE TABLE orders (order_id INTEGER PRIMARY KEY
, user_id INTEGER
, item_total REAL
, shipping_cost NUMERIC
, discounts_applied NUMERIC
, payment_reject INTEGER);
INSERT INTO orders(user_id, item_total, shipping_cost, discounts_applied
, payment_reject) VALUES (9852,60.69,10,0,FALSE),
(2784,123.91,15,0,FALSE), (1619,119.75,15,0,FALSE), (9725,151.92,15,0,FALSE),
(8892,153.27,15,0,FALSE), (7105,156.86,25,0,FALSE), (4345,136.09,15,0,FALSE),
(7779,134.93,15,0,FALSE), (3874,157.27,15,0,FALSE), (5102,108.3,10,0,FALSE),
(3098,59.97,10,0,FALSE), (6584,124.92,15,0,FALSE), (5136,111.06,10,0,FALSE),
(1869,113.44,20,0,FALSE), (3830,129.63,15,0,FALSE), (9852,70.69,10,0,FALSE),
(2784,134.91,15,0,FALSE), (1619,129.75,15,0,FALSE), (9725,161.92,15,0,FALSE),
(8892,163.27,15,0,FALSE), (7105,166.86,25,0,FALSE), (4345,146.09,15,0,FALSE),
(7779,144.93,15,0,FALSE), (3874,167.27,15,0,FALSE), (5102,118.3,10,0,FALSE),
(3098,69.97,10,0,FALSE), (6584,134.92,15,0,FALSE), (5136,121.06,10,0,FALSE),
(1869,123.44,20,0,FALSE), (3830,139.63,15,0,FALSE);
CREATE INDEX orders_idx_1 ON orders(user_id, item_total DESC);
the above query will give:
user_id item_total total_spent
---------- ---------- -----------
7105 156.86 373.72
3874 157.27 354.54
8892 153.27 346.54
9725 151.92 343.84
4345 136.09 312.18
7779 134.93 309.86
3830 129.63 299.26
6584 124.92 289.84
2784 123.91 288.82
1619 119.75 279.5
(If you get a syntax error from the query now, it's because you're using an old version of sqlite that doesn't support window functions.)
select
concat(fullvisitorid,cast(visitid as string)) as unique_session_id
,case
when h.item.productSku is not null then h.hitNumber
else max(h.hitnumber)
end
,h.item.transactionid
,h.item.itemrevenue/pow(10,6)
,h.item.productSku
from `myproject.mydataset.ga_sessions_20180101`, unnest(hits) as h
group by 1
Looking at case statement above (line 3)
How do I return that hitnumber where the productsku is populated
otherwise return the max hitnumber and then group this by the unique_session_id?
How to filter out transactionid's that contain '_ABC' at the same time?
I would suggest doing the grouping and finding the max hit number in a subquery. If you are going to use an aggregate function like MAX() in the select clause, then you need to group on or have aggregate functions for the other fields in the select. It can be useful to do aggregate sub-queries using common table expressions.
WITH data AS (
SELECT
CONCAT(fullvisitorid, CAST(visitid AS string)) AS unique_session_id,
h.hitNumber,
h.item.transactionid,
h.item.itemrevenue/POW(10,6) AS itemRevenue,
h.item.productSku
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801`,
UNNEST(hits) AS h
),
max_hits AS (
SELECT
unique_session_id,
MAX(hitNumber) AS max_hit_number
FROM data
GROUP BY 1
)
SELECT
d.unique_session_id,
CASE
WHEN d.productSku IS NOT NULL THEN d.hitNumber
ELSE m.max_hit_number
END,
d.transactionid,
d.itemrevenue,
d.productSku
FROM
data AS d JOIN max_hits AS m
ON d.unique_session_id = m.unique_session_id