I wrote the following T-SQL query to select count value of a particular table.
SELECT
COUNT(Item1) AS ITEM_COUNT, Item1 AS ITEM
FROM
[cloths_DB].[dbo].[Suggetion_DB]
WHERE
[Type] = 'Dockers' and [Age] = '25'
GROUP BY
Item1
UNION ALL
SELECT
COUNT(Item2) AS ITEM_COUNT, Item2 AS ITEM
FROM
[cloths_DB].[dbo].[Suggetion_DB]
WHERE
[Type] = 'Dockers' and [Age] = '25'
GROUP BY
Item2
ORDER BY
ITEM_COUNT DESC
And I get the following results:
ITEM_COUNT ITEM
-------------------------
7 Tommy
5 Denim shorts
4 Boxers
3 Diesel_D
3 Emerald
3 Jockey
2 Polo_D
2 Polo_D
2 Tommy
2 Gucci
I need to get highest number of item record in above result table. For example there is 7 number of "Tommy" in first row and 2 number of "Tommy" 9th row. So altogether there is 9 number of "Tommy" which is highest in above result.
How do I need to change the above query to get this result?
Select top 1 * from ( select sum(item_count) as total, item from (
SELECT
COUNT(Item1) AS ITEM_COUNT, Item1 AS ITEM
FROM
[cloths_DB].[dbo].[Suggetion_DB]
WHERE
[Type] = 'Dockers' and [Age] = '25'
GROUP BY
Item1
UNION ALL
SELECT
COUNT(Item2) AS ITEM_COUNT, Item2 AS ITEM
FROM
[cloths_DB].[dbo].[Suggetion_DB]
WHERE
[Type] = 'Dockers' and [Age] = '25'
GROUP BY
Item2
ORDER BY
ITEM_COUNT DESC
) group by item order by total desc)
If I understand you correctly, for each ITEM, you only want to see one row (with the largest count), but if you can provide us with sample data, we can figure out better. But assume my understanding is correct, the following code should work for you
with c as (
SELECT
COUNT(Item1) AS ITEM_COUNT, Item1 AS ITEM
FROM
[cloths_DB].[dbo].[Suggetion_DB]
WHERE
[Type] = 'Dockers' and [Age] = '25'
GROUP BY
Item1
UNION ALL
SELECT
COUNT(Item2) AS ITEM_COUNT, Item2 AS ITEM
FROM
[cloths_DB].[dbo].[Suggetion_DB]
WHERE
[Type] = 'Dockers' and [Age] = '25'
GROUP BY
Item2
)
, c2 as (
select item_count, item
, rnk=row_number() over (partition by Item order by item_count desc)
from c
)
select item_count, item from c2
where rnk = 1;
Related
I have items that can have many prices. I want a result table that has all the items itself and only the latest price of the item for a given region.
item
id
name
1
banana
2
apple
price
id
item_id
region
price
date
1
1
USA
10
1-1-2021
2
1
USA
20
2-1-2021
3
2
USA
30
1-1-2021
4
2
Canada
40
2-1-2021
result (should look like this)
id
name
region
price
date
1
banana
USA
20
2-1-2021
2
apple
USA
30
1-1-2021
I tried this but it returns all the rows from both tables.
select *
from item
LEFT JOIN price p on p.item_id = item.id
where p.created_at in (
select max(price.created_at)
from price
where p.id = price.id
)
and p.region = 'USA'
I fail to understand what I have to do to reduce the result table to only the rcords with the latest prices for each item.
Try this:
SELECT p.id, i.name, p.region, p.price, p.date
FROM price p
INNER JOIN (SELECT item_id, MAX(date) AS date FROM price GROUP BY item_id) t
ON t.item_id = p.item_id AND t.date = p.date
JOIN item i
ON p.item_id = i.id
WHERE p.region = 'USA'
Part of the reason your code did not work is that, in your WHERE clause, you are filtering by the maximum date of all the records in the price table.
This is a typical use-case for row_number():
select *
from item i left join
(select p.*,
row_number() over (partition by id order by created_at desc) as seqnum
from price p
where p.region = 'USA'
) p
on p.item_id = i.id and seqnum = 1;
I'm trying to get the percentage of this query per row. So my query is this:
SELECT ITEM, AVG_VAL/sum(AVG_VAL) * 100 as PERCENT_TOTAL
FROM
(SELECT
'item 1' AS ITEM,
AVG(VAL) AS AVG_VAL
FROM TABLE1
WHERE DATE(t_stamp) BETWEEN '2016-06-02' AND '2016-06-02'
UNION ALL
SELECT
'item 2' AS ITEM,
AVG(VAL) AS AVG_VAL
FROM TABLE2
WHERE DATE(t_stamp) BETWEEN '2016-06-02' AND '2016-06-02') as t
The data for the first table (TABLE1) is
ITEM | AVG_VAL
item 1 | 45,042,179
The data for the second table (TABLE2) is
ITEM | AVG_VAL
item 2 | 30,428,453
I was hoping to get the output
ITEM | PERCENT_TOTAL
item 1 | 59.68
item 2 | 40.32
but when i try to group it by ITEM
SELECT ITEM, AVG_VAL/sum(AVG_VAL) * 100 as PERCENT_TOTAL
FROM
(SELECT
'item 1' AS ITEM,
AVG(VAL) AS AVG_VAL
FROM TABLE1
WHERE DATE(t_stamp) BETWEEN '2016-06-02' AND '2016-06-02'
UNION ALL
SELECT
'item 2' AS ITEM,
AVG(VAL) AS AVG_VAL
FROM TABLE2
WHERE DATE(t_stamp) BETWEEN '2016-06-02' AND '2016-06-02') as t
GROUP BY ITEM
I get
ITEM | PERCENT_TOTAL
item 1 | 100
item 2 | 100
I was also hoping I can show the total for the percent_total column, so that it will show
ITEM | PERCENT_TOTAL
item 1 | 59.68
item 2 | 40.32
Total | 100
Here's one way...
SELECT x.*
, ROUND(avg_val/total * 100,2) pct
FROM
( SELECT * FROM table1
UNION
SELECT * FROM table2
) x
JOIN
( SELECT SUM(avg_val) total
FROM
( SELECT * FROM table1
UNION
SELECT * FROM table2
) n
) y
I have a table of products sales
id product_id price_sold
1 1 500
2 1 300
3 2 100
4 3 200
5 3 100
I want to be able to sum the prices by different subsets of products, say: sum of prices per the group of proucts 1,2. and another calculation of sum of prices per the group of products 2,3, so the needed result will be:
group 1, 900
group 2, 400
Can you help with efficient and elegant way to do that?
Doing what you want is a bit challenging, because the groups overlap. You have two options. The first is to do conditional aggregation and put the results in columns:
select sum(case when product_id in (1, 2) then price_sold end) as group1,
sum(case when product_id in (2, 3) then price_sold end) as group2
from productsales ps;
To get the results on separate rows, you could then pivot this result. Or, you could do the calculation directly. For this to work, you need to construct a table describing the groups:
select pg.grpid, sum(ps.price_sold)
from productsales ps
join
(
select 1 as grpid, 1 as product_id
union all
select 1 as grpid, 2 as product_id
union all
select 2 as grpid, 2 as product_id
union all
select 2 as grpid, 3 as product_id
) pg on ps.product_id = pg.product_id
group by pg.grpid;
SQL Fiddle:
SELECT 'GROUP 1' AS `Group`, SUM(price_sold) AS PriceSum
FROM MyTable
WHERE product_id = 1 OR product_id = 2
UNION
SELECT 'GROUP 2', SUM(price_sold)
FROM MyTable
WHERE product_id = 2 OR product_id = 3
The result looks like:
I have a query I cannot wrap my head around. Let's say I have this table, items with 6 records
item_id passage_id
========== ==========
6 0
5 3
4 0
3 0
2 3
1 3
To get the records by descending item_id, I run the statement SELECT * FROM items ORDER BY item_id DESC, and the result is simply the same as the source table above.
But now it gets tricky. I now want to sort by descending item_id, but if there are other items with the same passage_id, I want them grouped by that passage_id.
item_id passage_id
========== ==========
6 0
5 3
2 3
1 3
4 0
3 0
How can I do this in a single SQL statement? The order is crucial because I need preserve it even when a limit is used:
SELECT * FROM items ORDER BY ??? LIMIT 0, 3
item_id passage_id
========== ==========
6 0
5 3
2 3
SELECT * FROM items ORDER BY ??? LIMIT 2, 3
item_id passage_id
========== ==========
1 3
4 0
3 0
EDIT: Here's the answer, taken from Gordon Linoff's answer below
SELECT i.item_id, i.passage_id
FROM items i LEFT JOIN (
SELECT i.passage_id, MAX(i.item_id) AS imax_id
FROM items i
GROUP BY i.passage_id
) imax
ON i.passage_id = imax.passage_id
ORDER BY CASE WHEN i.passage_id=0 THEN i.item_id ELSE imax.imax_id END DESC, i.item_id DESC;
If I understand correctly, you want to do something like keep the passage_ids together and sort these groups by the item ids. The following should actually do this:
select i.item_id, i.passage_id
from items i join
(select i.passage_id, max(i.item_id) as maxiid
from items i
group by i.passage_id
) imax
on i.passage_id = i.passage_id
order by imax.maxiid,
i.item_id desc;
But, it will not produce your ordering, because of passage_id = 0. For these, you seem to want them based only on the item_id itself. So, I think this encapsulates your logic:
select i.item_id, i.passage_id
from items i join
(select i.passage_id, max(i.item_id) as maxiid
from items i
group by i.passage_id
) imax
on i.passage_id = i.passage_id
order by (case when i.passage_id = 0 then i.item_id else imax.maxiid end) desc,
i.item_id desc;
Say I have two tables I want to join.
Categories:
id name
----------
1 Cars
2 Games
3 Pencils
4 Books
And items:
id categoryid itemname
---------------------------
1 1 Ford
2 1 BMW
3 1 VW
4 2 Tetris
5 2 Pong
6 3 Foobar Pencil Factory
I want a query that returns the category and the last maximum N (for example: 2) itemname:
category.id category.name item.id item.itemname
-------------------------------------------------
1 Cars 2 BMW
1 Cars 3 VW
2 Games 4 Tetris
2 Games 5 Pong
3 Pencils 6 Foobar Pencil Factory
4 Books NULL NULL
I want write a query like below:
Select * From categories c
Left Join (select * from items order by id desc) i
On c.id=i=categoryid
AND LIMIT 2 #comment: N=2 this line not supported
Where i.categoryid = c.id
Group By c.id
Thanks!
I'm not saying it's efficient, but it should work:
SELECT c.*, i.id, i.itemname
FROM categories c
LEFT JOIN
(SELECT i.*
FROM items i
LEFT JOIN items i2 ON i.categoryid = i2.categoryid AND i2.id > i.id
GROUP BY i.id
HAVING COUNT(*) < 2 # this 2 = N
) i ON c.id = i.categoryid
Check http://sqlfiddle.com/#!2/9a132/1
SELECT *
FROM Categories c
LEFT JOIN -- Items i
(
SELECT * FROM Items WHERE LOCATE(id,
(
SELECT GROUP_CONCAT(it.itemids) AS its
FROM (
SELECT (SUBSTRING_INDEX(GROUP_CONCAT(CONVERT(id, CHAR(8))
ORDER BY id DESC), ',', 2)) AS itemids
FROM Items
GROUP BY categoryid
) it
)) <> 0
) i
ON i.categoryid = c.id;
where N=2 is: SUBSTRING_INDEX(GROUP_CONCAT(CONVERT(id, CHAR(8)) ORDER BY id DESC), ',', 2)
Because GROUP_CONCAT is by default sort ASC ; above will become SUBSTRING_INDEX(GROUP_CONCAT(CONVERT(id, CHAR(8)) ), ',', -2). But GROUP_CONCAT result is truncated to max len 1024 (group_concat_max_len).