sql - check for uniqueness of COMPOSITE key - sql

Can somebody please help me with this difficulty I am having?
I would like to check some data whether it is valid, so a small part of the validation consists of entity integrity where I check that my primary key is unique
SELECT order_id, COUNT(order_id)
FROM temp_order
GROUP BY order_id
HAVING ( COUNT(order_id) > 1 )
in this case, order_id is the primary key. This query works fine.
The problem:
I now have another table temp_orditem which has a composite primary key made up of 2 fields: order_id, product_id.
How can I check whether the primary key is unique (i.e. the combination of the 2 fields together)? Can I do the following?
SELECT order_id, product_id, COUNT(order_id), COUNT(product_id)
FROM temp_order
GROUP BY order_id, product_id
HAVING ( COUNT(order_id) > 1 AND COUNT(product_id)>1)

I would just write this:
SELECT order_id, product_id, COUNT(*) AS x
FROM temp_order
GROUP BY order_id, product_id
HAVING x > 1

This is the query you need:
select order_id, product_id, count(*)
from temp_order
group by order_id, product_id
having count(*) > 1

Related

SQL query to select single record when record may exist in another colum

i just need help putting together a query. Below is an example of what I would like to achieve:
Table name: Current_Orders_tbl
Indented output query
We can get an order without a transaction_id, or an order that has an order_id that is the same as a transaction_id in the table.
When I query the table, I would like to only see:
The order_id that contains a transaction_id that matches an already used order_id.
The null transaction_id if that order_id hasn't been used before
Thanks in advance
SELECT COALESCE(table2.order_id, table1.order_Id) AS order_id,
table1.order_name,
COALESCE(table2.transaction_id, table1.transaction_id) AS transaction_id
FROM current_orders_tbl AS table1 LEFT OUTER JOIN
Current_orders_tbl AS table2 ON table1.order_id = table2.transaction_iD
WHERE
(table1.transaction_id IS NULL and table2.order_id IS NULL) OR
Table2.order_id IS NOT NULL
We can use ROW_NUMBER here.
The partition will be done by order_name and we will sort by transaction_id:
WITH sub AS
(SELECT order_id, order_name, transaction_id,
ROW_NUMBER()
OVER (PARTITION BY order_name ORDER BY transaction_id DESC) AS rowNr
FROM Current_Orders_tbl)
SELECT order_id, order_name, transaction_id
FROM sub
WHERE rowNr = 1;
This will - according to your sample - fetch only that row per order_name having the highest transaction_id.
Try out here
Sidenote: If the result of that query should be sorted, I think adding ORDER BY order_id, order_name would be best here.
Try with exists and correlated subquery as the following:
select order_id, order_name, transaction_id
from table_name T
where
( /* for the 1st requirement: The order_id that contains a transaction_id that matches an already used order_id.*/
transaction_id is not null and
exists(select 1 from table_name D where D.order_id = T.transaction_id)
)
or
( /* for the 2nd requirement: The null transaction_id if that order_id hasn't been used before. */
transaction_id is null and
not exists(select 1 from table_name D where D.transaction_id = T.order_id)
)
See demo

Select multiple columns with not all columns mentioned in Groupby - Postgres v12

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

Select distinct values from union

I have three tables (sales orders, invoices, purchase orders)
sales_order
------------
so_id (primary key)
item_id (foreign key)
entry_date
invoice
------------
invc_id (primary key)
item_id (foreign key)
entry_date
purchase_order
------------
po_id (primary key)
item_id (foreign key)
entry_date
and they all refer to one central table (item):
item_id (pk)
I am trying to write a sql query that will return all items with activity within a date range.
This is what I've come up with:
select distinct item_id from sales_order where entry_date between ? and ?
union
select distinct item_id from invoice where entry_date between ? and ?
union
select distinct item_id from purchase where entry_date between ? and ?
I think this is the correct solution, but I'm not sure how to test it.
Question 1:
Does the "distinct" keyword apply to all of the statements or only to each statement? i.e., will each query return a distinct set but when you "union" them together it can show duplicates?
Question 2:
Is there a way to return the total (unique) item count (as a separate query)? Like:
select count(
select distinct item_id from sales_order where entry_date between ? and ?
union
select distinct item_id from invoice where entry_date between ? and ?
union
select distinct item_id from purchase where entry_date between ? and ?
)
??
The distinct is redundant. I usually write such as query as:
select item_id from sales_order where entry_date between ? and ?
union -- intentionally removing duplicates
select item_id from invoice where entry_date between ? and ?
union
select item_id from purchase where entry_date between ? and ?;
To return the total count, you can use a subquery:
select count(*)
from (select item_id from sales_order where entry_date between ? and ?
union -- intentionally removing duplicates
select item_id from invoice where entry_date between ? and ?
union
select item_id from purchase where entry_date between ? and ?
) i;

Sorting Records on the Basis of Number of Items in a Group- SQL Server

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;

add primary row to query results

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