Finding duplicate values in multiple rows in SQL Server table - sql

I have a SQL Server database table with this sample data:
ProductID GenericID MG
---------------------------------
1 1 2g
1 2 5g
2 2 5g
3 1 2g
3 2 5g
4 1 2g
5 1 2g
5 3 7g
6 2 5g
7 1 2g
8 1 2g
I want to find out the query to select data
if I select 'ProductID=1' then the query should check what 'GenericID' are associated with 'ProductID=1'
In above data case if user select 'ProductID=1' then query will check 'GenericID=1' and 2 are associated with 'ProductID=1'.
Then after I want to go through all rows and select those rows who has the same Unique 'ProductID' and also having only 'GenericID=1 and 2'.
as in above case the final output will be as shown below....
I select 'ProductID=1' and output has four rows, because only ProductId 3 has same 'GenericID' as were of 'ProductId=1'
If I select only ProductId=1 then I want to get all the rows with the same exact set of GenericID values as ProductID=1, which is the set { 1, 2 } in my sample data. I am struggling with the query logic.
For example - I select ProductID=1, this is the output that I want is as follows, because ProductID 3 has the same set of GenericID values as ProductID 1.
ProductID GenericID MG
-------------------------------
1 1 2g
1 2 5g
3 1 2g
3 2 5g
GenericID can be on or multiple dynamic values.
Another example - if I select ProductID=7, this is the output I want:
In this example - It will only get those results that are having only GenericID=1 because ProductID=7 has only GenericID=1. any set of productID which is having 'GenericID=1' and also that set includes other 'GenericID' will be neglected.
ProductID GenericID MG
------------------------------
7 1 2g
8 1 2g
4 1 2g
I need to find out the query to select the required output.
I want all of the products that have the same set of generic id's as the predicate product.

How about
SELECT *
FROM yourtable
WHERE
GenericID in (SELECT GenericID FROM yourtable WHERE ProductID=1)
Update:
If the whole set of GenericIDs needs to match, this should work (assuming ProductID, GenericID is unique):
WITH yourtable_gids AS (
SELECT
ProductID,
STRING_AGG(GenericID, ',') WITHIN GROUP (ORDER BY GenericID) as GenericIDs
FROM yourtable
GROUP BY ProductID
)
SELECT y.*
FROM yourtable y
JOIN yourtable_gids yg ON y.ProductID=yg.ProductID
WHERE
yg.GenericIDs in (SELECT GenericIDs FROM yourtable_gids WHERE ProductID=1)

So if i interpret the question right it's
I select on a product Id, and want to additionaly have every product with the same generic IDs as the ones I got.
select * from products
where productID = X
or genericId in (select genericId from products where product ID = X)
This should be the answer if I got your question right.

Related

Merge row values based on other column value

I'm trying to merge the values of two rows based on the value of another row in a different column. Below is my based table
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3
100
1
C
4
100
1
D
5
20
1
Here is the SQL query I used
select customer_id, property_id, bookings_per_customer, cancellations_per_customer
from table
And this is what I want to see. Any ideas the query to get this would be? We use presto SQL
Thanks!
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3 , 4
100
1
D
5
20
1
We can try:
SELECT
customer_id,
ARRAY_JOIN(ARRAY_AGG(property_id), ',') AS properties,
bookings_per_customer,
cancellations_per_customer
FROM yourTable
GROUP BY
customer_id,
bookings_per_customer,
cancellations_per_customer;

Finding duplicate **Set of Values** in multiple rows in SQL Server table

I have a SQL Server database table with this sample data:
ProductID GenericID MG
---------------------------------
1 1 2g
1 2 5g
2 2 5g
3 1 2g
3 2 5g
4 1 2g
5 1 2g
5 3 7g
6 2 5g
7 1 2g
8 1 2g
I want to find out the query to select data
if I select ProductID=1 then the query should check what GenericID are associated with ProductID=1
In above data case if user select ProductID=1 then query will check GenericID=1 and 2 are associated with ProductID=1.
Then after I want to go through all rows and select those rows who has the same Unique ProductID and also having only GenericID=1 and 2.
as in above case the final output will be as shown below....
I select ProductID=1 and output has four rows, because only ProductId 3 has same GenericID as were of ProductId=1.
If I select only ProductId=1 then I want to get all the rows with the same exact set of GenericID values as ProductID=1, which is the set { 1, 2 } in my sample data. I am struggling with the query logic.
For example - I select ProductID=1, this is the output that I want is as follows, because ProductID 3 has the same set of GenericID values as ProductID 1.
ProductID GenericID MG
-------------------------------
1 1 2g
1 2 5g
3 1 2g
3 2 5g
GenericID can be on or multiple dynamic values.
Another example - if I select ProductID=7, this is the output I want:
In this example - It will only get those results that are having only GenericID=1 because ProductID=7 has only GenericID=1. any set of productID which is having GenericID=1 and also that set includes other GenericID will be neglected.
ProductID GenericID MG
------------------------------
7 1 2g
8 1 2g
4 1 2g
I need to find out the query to select the required output.
I want all of the products that have the same set of generic id's as the predicate product.
The simplest method is probably to use string_agg():
with t as (
select productID, string_agg(genericId, ',') within group (order by genericId) as genericIds
from sample
group by productID
)
select s.*
from t join
t t2
on t.genericIds = t2.genericIds and t2.productId = 1 join
sample s
on s.productId = t.productId;
Gordon, thanks a lot for your prompt response, basically I forget to inform you that I am using SQL 2014 and that's why string_agg(): action function wasn't helpful for me but I really appreciate your help and the prompt response that make my day. Here I created my query with the help of your other query and you became and very helpful resource for me.
select PG.PID2 as Alternatives
from (select d1.ProductID as PID1, d2.ProductID as PID2
from (select distinct ProductID from ProductsGenerics Where ProductID=#PID) d1 cross join
(select distinct ProductID from ProductsGenerics) d2
) PG left outer join
ProductsGenerics e1
on e1.ProductID = PG.PID1 full outer join
ProductsGenerics e2
on PG.PID2 = e2.ProductID and e1.genericid = e2.GenericID-- and e1.MG = e2.MG
group by PG.PID1, PG.PID2
having SUM(case when e1.GenericID is null then 1 else 0 end) = 0 and
SUM(case when e2.GenericID is null then 1 else 0 end) = 0

Left Join Display All Data From Table1 and Table2

I am trying to do a left join so that I get all of my rows from Table 1 even if there is no value corresponding to it in the second table.
My structures are:
Location Table:
ID LocName
1 Trk1
2 Trk2
3 Trk3
4 Unk
Quantity Table:
ID PartID Quantity LocationID
1 1 2 1
2 3 12 2
3 2 6 1
4 6 8 3
5 6 5 1
I am trying to join but also make a query on a specific PartID. My query is:
SELECT
INV_LOCATIONS.ID AS LocationID,
INV_LOCATIONS.NAME AS LocationName,
INV_QUANTITY.QUANTITY AS Quantity
FROM INV_LOCATIONS
LEFT JOIN INV_QUANTITY ON INV_LOCATIONS.ID = INV_QUANTITY.LOCATION_ID
WHERE INV_QUANTITY.PART_ID = 1;
My output right now would be:
ID LocName Quantity
1 Trk1 5
3 Trk3 8
The Desired output is:
ID LocName Quantity
1 Trk1 5
2 Trk2 NULL/0
3 Trk3 8
4 Unk NULL/0
I assume it is because I have the WHERE INV_QUANTITY.PART_ID = 1 and that is forcing it to be in the quantity table. I need to be able to verify it is on the right part but how do I also include it if it doesn't exist. I know I have done something very similar before but I cannot remember which project and so I cannot find the code anywhere.
You need to move the filtering logic to the ON clause:
SELECT il.ID AS LocationID, il.NAME AS LocationName,
iq.QUANTITY AS Quantity
FROM INV_LOCATIONS il LEFT JOIN
INV_QUANTITY iq
ON il.ID = iq.LOCATION_ID AND iq.PART_ID = 1;

Derby DB last x row average

I have the following table structure.
ITEM TOTAL
----------- -----------------
ID | TITLE ID |ITEMID|VALUE
1 A 1 2 6
2 B 2 1 4
3 C 3 3 3
4 D 4 3 8
5 E 5 1 2
6 F 6 5 4
7 4 5
8 2 8
9 2 7
10 1 3
11 2 2
12 3 6
I am using Apache Derby DB. I need to perform the average calculation in SQL. I need to show the list of item IDs and their average total of the last 3 records.
That is, for ITEM.ID 1, I will go to TOTAL table and select the last 3 records of the rows which are associated with the ITEMID 1. And take average of them. In Derby database, I am able to do this for a given item ID but I cannot make it without giving a specific ID. Let me show you what I've done it.
SELECT ITEM.ID, AVG(VALUE) FROM ITEM, TOTAL WHERE TOTAL.ITEMID = ITEM.ID GROUP BY ITEM.ID
This SQL gives the average of all items in a list. But this calculates for all values of the total tables. I need last 3 records only. So I changed the SQL to this:
SELECT AVG(VALUE) FROM (SELECT ROW_NUMBER() OVER() AS ROWNUM, TOTAL.* FROM TOTAL WHERE ITEMID = 1) AS TR WHERE ROWNUM > (SELECT COUNT(ID) FROM TOTAL WHERE ITEMID = 1) - 3
This works if I supply the item ID 1 or 2 etc. But I cannot do this for all items without giving an item ID.
I tried to do the same thing in ORACLE using partition and it worked. But derby does not support partitioning. There is WINDOW but I could not make use of it.
Oracle one
SELECT ITEMID, AVG(VALUE) FROM(SELECT ITEMID, VALUE, COUNT(*) OVER (PARTITION BY ITEMID) QTY, ROW_NUMBER() OVER (PARTITION BY ITEMID ORDER BY ID) IDX FROM TOTAL ORDER BY ITEMID, ID) WHERE IDX > QTY -3 GROUP BY ITEMID ORDER BY ITEMID
I need to use derby DB for its portability.
The desired output is this
RESULT
-----------------
ITEMID | AVERAGE
1 (9/3)
2 (17/3)
3 (17/3)
4 (5/1)
5 (4/1)
6 NULL
As you have noticed, Derby's support for the SQL 2003 "OLAP Operations" support is incomplete.
There was some initial work (see https://wiki.apache.org/db-derby/OLAPOperations), but that work was only partially completed.
I don't believe anyone is currently working on adding more functionality to Derby in this area.
So yes, Derby has a row_number function, but no, Derby does not (currently) have partition by.

SQL query to print mirror labels

I want to print labels in words as returned by a SQL query such as follow.
1 2 3
4 5 6
When I want to print the reverse of those labels, I have to print them as follow
3 2 1
6 5 4
In my real case, I have 5 colums by 2 rows, how can I formulate my query so that my records are ordered like the second one.
The normal ordering is handled by word, so my query is like
SELECT * FROM Products ORDER BY Products.id
I'm using MS Access =(
EDIT :
Just to make it clear
I'd like my records to be ordered such as
3 2 1 6 5 4 9 8 7 12 11 10
EDIT2 :
my table looks like this
ID ProductName
1 Product1
2 Product2
3 Product3
n Product[n]
I want the ids to be returned as I mentioned above
SELECT * FROM Products ORDER BY Products.id desc
Alternately if your query at the moment is really giving you this:
select col1, col2, col3 from products order by products.id;
why not use
select col3, col2, col1 from products order by products.id;