How do I add a primary row to a query result in MSSQL 2005. Here's an example of what I need to return?
Here are the two queries
query 1
select product_id, sku from products
query 2
select product_id, sku from childproducts
The results should look like this. (without the query 1, of course)
row 1: products.product_id, products.sku (comes from one parent table)
row 2: childproducts.product_id, childproducts.sku (comes from child table)
row 3: childproducts.product_id, childproducts.sku (comes from child table)
You can combine them using UNION ALL, e.g.
select 1 as Sorter, product_id, sku from products
UNION ALL
select 2, product_id, sku from childproducts
ORDER BY Sorter, product_id
Notice I added the Sorter column to make the parent set appear before the child products. If you had to exclude it, but still show them in that order:
select product_id, sku
from (
select 1 as Sorter, product_id, sku from products
UNION ALL
select 2, product_id, sku from childproducts
) X
ORDER BY Sorter, product_id
If I understand correctly, you want to add a primary key that maintains the ordering of the rows, so the children immediately follow the parent. The following code does this using row_number() to assign the new id:
select row_number() over (order by parentproduct_id, isparent desc) as newid,
product_id, sku
from ((select product_id, sku, product_id as parentproduct_id, 1 as isparent
from productions
) union all
(select product_id, sku, parentproduct_id, 0 as isparent
from childproducts
)
) p
If you don't actually want an id in the data but just want the sort order, then add this:
order by parentproduct_id, isparent desc
Related
I would like to know the sum of a value in the first n items in a related table. For example, I want to get the sum of a companies first 6 invoices (the invoices can be sorted by ID asc)
Current SQL:
SELECT invoices.company_id, SUM(invoices.amount)
FROM invoices
JOIN companies on invoices.company_id = companies.id
GROUP BY invoices.company_id
This seems simple but I can't wrap my head around it.
Consider also below approach
select company_id, (
select sum(amount)
from t.amounts amount
) as top_six_invoices_amount
from (
select invoices.company_id,
array_agg(invoices.amount order by invoices.invoice_id limit 6) amounts
from your_table invoices
group by invoices.company_id
) t
You can create order row numbers to the lines in a partition based on invoice id and filter to it, something like this:
with array_table as (
select 'a' field, * from unnest([3, 2, 1 ,4, 6, 3]) id
union all
select 'b' field, * from unnest([1, 2, 1, 7]) id
)
select field, sum(id) from (
select field, id, row_number() over (partition by a.field order by id desc) rownum
from array_table a
)
where rownum < 3
group by field
More examples for analytical examples here:
https://medium.com/#aliz_ai/analytic-functions-in-google-bigquery-part-1-basics-745d97958fe2
https://cloud.google.com/bigquery/docs/reference/standard-sql/analytic-function-concepts
I have a table which contain review_id,product_id,ratings,reviewer_id,review_comments. The table i have is as below.
My need is quite simple but I have issues figuring it out. Need is to get product_id, rating, reviewer_id and review_comments of the product_id which has the max value of review_id
With below query, I am able to get product_id and review_id properly.
SELECT product_id,max(review_id) as review_id
FROM public.products Group by product_id;
But when I try to add ratings, reviewer_id, and review_comments, it raises an error that those columns have to be part of a groupby and if I add those columns, grouping gets disturbed since I need grouping only on product_id and nothing else.
Is there a way to solve this?
My expected result should contain all row content with review_id 7,5,8 since for product_id 1 review_id 7 is highest and for product_id 2 review_id 5 is highest and for product_id 3 review_id 8 is highest.
Try PostgreSQL's DISTINCT ON:
SELECT DISTINCT ON (product_id)
product_id,
review_id,
rating,
reviewer_id,
review_comments
FROM products
ORDER BY product_id, review_id DESC;
This will return the first row for each product_id in the ORDER BY order.
This can be done with NOT EXISTS:
select p.product_id, p.rating, p.reviewer_id, p.review_comments
from public.products p
where not exists (
select 1 from public.products
where product_id = p.product_id and review_id > p.review_id
)
You can try below way-
select * from tablename a
where review_id =(select max(review_id) from tablename b where a.product_id=b.product_id)
or use row_number()
select * from
(
select *, row_number() over(partition by product_id order by review_id desc) as rn
from tablename
)A where rn=1
I am sorry if this seems too easy but I was asked this question and I couldn't answer even after preparing SQL thoroughly :(. Can someone answer this?
There's a table - Seller id, product id, warehouse id, quantity of products at each warehouse for each product as per each seller.
We have to list the Product Ids with Seller Id who has highest number of products for that product and the total number of units he has for that product.
I think I got confused because there were 3 keys in the table.
It's not quite clear which DBMS you are using currently. The below should work if your DBMS support window functions.
You can find count of rows for each product and seller, rank each seller within each product using window function rank and then use filter to get only top ranked sellers in each product along with count of units.
select
product_id,
seller_id,
no_of_products
from (
select
product_id,
seller_id,
count(*) no_of_products,
rank() over (partition by product_id order by count(*) desc) rnk
from your_table
group by
product_id,
seller_id
) t where rnk = 1;
If window functions are not supported, you can use correlated query to achieve the same effect:
select
product_id,
seller_id,
count(*) no_of_products
from your_table a
group by
product_id,
seller_id
having count(*) = (
select max(cnt)
from (
select count(*) cnt
from your_table b
where b.product_id = a.product_id
group by seller_id
) t
);
Don't know why having id columns would mess you up... group by the right columns, sum up the totals and just return the first row:
select *
from (
select sellerid, productid, sum(quantity) as total_sold
from theres_a_table
group by sellerid, productid
) x
order by total_sold desc
fetch first 1 row only
If I do not think about optimization, straight forward answer is like this
select *
from
(
select seller_id, product_id, sum(product_qty) as seller_prod_qty
from your_table
group by seller_id, product_id
) spqo
inner join
(
select product_id, max(seller_prod_qty) as max_prod_qty
from
(
select seller_id, product_id, sum(product_qty) as seller_prod_qty
from your_table
group by seller_id, product_id
) spqi
group by product_id
) pmaxq
on spqo.product_id = pmaxq.product_id
and spqo.seller_prod_qty = pmaxq.max_prod_qty
both spqi (inner) and sqpo (outer) give you seller, product, sum of quantity across warehouses. pmaxq gives you max of each product again across warehouses, and then final inner join picks up sum of quantities if seller has highest (max) of the product (could be multiple sellers with the same quantity). I think this is the answer you are looking for. However, I'm sure query can be improved, since what I'm posting is the "conceptual" one :)
I have a set of records and I want to sort these records on the basis of the number of items in a group.
I want to arrange the records in such a way that Products with maximum number of items are at the top i.e. the required order is- Product_ID 3 (with 6 items), then Product_ID 1 (with 5 items) and the last one would be Product_ID 2(with 3 items).
The following query returns the count of the items with same Product_ID, however, I want Item_Name, Item_Description and Item_Number to be arranged as well.
Select Product_ID, Count(*) from Product group by Product_ID order by Count(*) DESC
I have tried another query as follows, but I know I am wrong somewhere that it is not giving the desired results and I can't think of a possible solution:
Select Product_ID, Item_Name, Item_Description, Item_Number from Product
group by Product_ID,item_name,item_description,item_number
order by COUNT(product_ID)
Thanks in advance for your help!!
Select Product_ID, Item_Name, Item_Description, Item_Number
from Product
order by COUNT(1) over (partition by Product_ID) desc
I assume you want to group by the ID only but you want to list all other fields, you don't need to group by at all if you just want to order by:
SELECT product_id,
item_name,
item_description,
item_number
FROM product p1
ORDER BY (SELECT Count(product_id)
FROM product p2
WHERE p1.product_id = p2.product_id) DESC
Try using an alias:
Select Product_ID, Count(*) AS num_products from Product group by Product_ID order by num_products DESC;
I have a query that will return results from 2 tables into 1 using a UNION ALL, which all works as I need it to. However I need to run a GROUP BY and an ORDER BY on the returned dataset however I am getting many errors and I'm not sure how to solve it.
Here is my Query:
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
This will return a results set such as this:
ProductID Quantity
15 2
20 2
15 1
8 5
5 1
I then want to run a GROUP BY on the ProductID field and then finally an ORDER BY DESC on the Quantity field. So in the final output, this particular results set will finally result in this:
ProductID
8
15
20
5
I can then run queries on this result set as I usually do
EDIT:
As stated above, but maybe not implied enough is that I will need to run queries on the returned results, which isn't working as you cannot run a query on a set of results that have an ORDER BY clause (so far as I gathered from the error list)
If you want more information on the problem, here it is:
From this results set, I want to get the products from the product table that they relate to
SELECT * FROM Products WHERE ID IN (
SELECT ProductID
FROM
(
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
) v
GROUP BY ProductID
ORDER BY SUM(Quantity) DESC
)
However, I get this error: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
The output of products need to be in the order that they are returned in the sub query (By quantity)
SELECT Products.*
FROM Products
INNER JOIN
(
SELECT ProductID, Sum(Quantity) as QuantitySum
from
(
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
) v
GROUP BY ProductID
) ProductTotals
ON Products.ID = ProductTotals.ProductID
ORDER BY QuantitySum DESC
will this work?
SELECT ProductID
from
(
SELECT ProductID, Quantity
FROM BasketItems
UNION ALL
SELECT ProductID, Quantity
FROM OrderItems
) temp
GROUP BY temp.ProductID
ORDER BY SUM(temp.Quantity) desc
Here's a cte version (no live test so please excuse blunders)
EDIT
;WITH myInitialdata_cte(ProductID,Quantity)
AS
(
SELECT ProductID, Quantity FROM BasketItems
UNION ALL
SELECT ProductID, Quantity FROM OrderItems
)
SELECT b.ID
FROM
myInitialdata_cte a
INNER JOIN Products b ON
a.ProductID = b.ID
GROUP BY ProductID
ORDER BY SUM(a.Quantity) DESC