Get higest value of each relation - sql

I have Project table, ProjectDesign Table and Design Table
So each project have multiple Designs and they are related by ProjectDesign table
Like this
Project Table
+------------+----------+
| ProjectKey | Name |
+------------+----------+
| 1 | Project1 |
| 2 | Project2 |
| 3 | Project3 |
+------------+----------+
ProjectDesign Table
+------------+-----------+
| ProjectKey | DesignKey |
+------------+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 1 | 4 |
| 1 | 5 |
+------------+-----------+
Design Table
+-----------+------+
| DesignKey | Name |
+-----------+------+
| 1 | Key1 |
| 2 | Key2 |
| 3 | Key3 |
| 4 | Key4 |
| 5 | Key5 |
+-----------+------+
That I want to do is to select MAX designKey of each project. I try as:
SELECT MAX([PD].[DesignKey])
FROM [Project] AS [p]
INNER JOIN [ProjectDesign] AS [PD] ON [PD].[ProjectKey] = [P].[ProjectKey]
INNER JOIN [Design] AS [D] ON [PD].[DesignKey] = [D].[DesignKey]
But it only gets one value, and its the highest design key, but I want highest design key of each project. How can I achieve that?

You can simply do this:
SELECT [p].ProjectKey, max([PD].[DesignKey])
FROM [Project] AS [p]
INNER JOIN [ProjectDesign] AS [PD] ON [PD].[ProjectKey] = [P].[ProjectKey]
INNER JOIN [Design] AS [D] ON [PD].[DesignKey] = [D].[DesignKey]
group by [p].ProjectKey;

Only bridge table is enough for you to get this
SELECT ProjectKey, max(DesignKey)
From ProjectDesign
Group by ProjectKey

You can use GROUP BY or a Windowing function to do this -- here is how to do it with a windowing function:
SELECT MAX([PD].[DesignKey]) OVER (PARTITION BY PD.ProjectKey) AS MAX_BY_PROJECT
FROM [Project] AS [p]
INNER JOIN [ProjectDesign] AS [PD] ON [PD].[ProjectKey] = [P].[ProjectKey]
INNER JOIN [Design] AS [D] ON [PD].[DesignKey] = [D].[DesignKey]

Related

SQL self join result of a select

I have two tables, lets call them A and B which I perform an inner join on.
select
A.id,
A.serial_number as serial,
concat(B.type, '-', B.primary, '-', B.secondary) as product_number, A.parent_id as parent
from A
inner join B on A.number_id = B.id) as T1
as a result I get a set that contains parents and children (1 per parent).
+----+--------+-----------------+--------+
| id | serial | product number | parent |
+----+--------+-----------------+--------+
| 1 | 123 | abc | null |
| 2 | 234 | cde | 1 |
| 3 | 456 | abc | null |
| 4 | 895 | cde | 2 |
+----+--------+-----------------+--------+
now I'd like to do a self join to get the following
+----+---------------+------------------------+---------------+-----------------------+
| id | serial parent | product_number parent | serial child | product_number child |
+----+---------------+------------------------+---------------+-----------------------+
| 1 | 123 | abc | 234 | cde |
| 2 | 456 | abc | 895 | cde |
+----+---------------+------------------------+---------------+-----------------------+
What would be the best approach for this, I simply couldn't find an easy solution... is there a way to join T1 with itself?
I think that's more joins:
select
ap.id as id_parent,
ap.serial_number as serial_parent,
concat_ws('-', bp.type, bp.primary, bp.secondary) as product_number_parent,
ac.child as id_child,
ac.serial_number as serial_child,
concat_ws('-', bc.type, bc.primary, bc.secondary) as product_number_child
from a ap
inner join a ac on ac.parent = ap.id
inner join b bp on bp.id = ap.astrol_number_id
inner join b bc on bc.id = ac.astrol_number_id
where ap.parent is null

Getting wrong data from relation

I have 2 tables:
DesignGroup table:
+--------------------------------------+--------+
| DesignGroupId | Name |
+--------------------------------------+--------+
| 9D32C543-24EA-497E-918E-387C8A66BF1A | Group1 |
| 532C543E-24EA-497E-918E-387C8A66BF1A | Group2 |
+--------------------------------------+--------+
Design table:
+-----------+---------------+--------------------------------------+
| DesignKey | Name | DesignGroupId |
+-----------+---------------+--------------------------------------+
| 1 | Design | 9D32C543-24EA-497E-918E-387C8A66BF1A |
| 2 | Design | 9D32C543-24EA-497E-918E-387C8A66BF1A |
| 3 | AnotherDesign | 532C543E-24EA-497E-918E-387C8A66BF1A |
+-----------+---------------+--------------------------------------+
As you can see multiple designs can have same DesignGroupId, So I make a query like:
DECLARE #DesignName VARCHAR(255) = 'Design'
SELECT
[D].[Name] AS [Display],
[D].[DesignKey] AS [Value]
FROM
[Design] AS [D]
JOIN
[DesignGroup] AS [DG] ON [D].[DesignGroupId] = [DG].[DesignGroupId]
GROUP BY
[D].[Name], [D].[DesignKey];
My desire result of this, is get only one value one [Display] and one [Value] of each DesignGroupId, so my desire result there was:
+---------------+-------+
| Display | Value |
+---------------+-------+
| Design | 1 |
| AnotherDesign | 3 |
+---------------+-------+
But I'm getting result foreach DesignKey like:
+---------------+-------+
| Display | Value |
+---------------+-------+
| Design | 1 |
| Design | 2 |
| AnotherDesign | 3 |
+---------------+-------+
How can I solve this? Regards
I don't see why you need to join the tables.
The results you want depend only on the data from the table [Design].
So GROUP BY [Name] and get the minimum value of [DesignKey]:
SELECT
[Name] AS [Display],
MIN([DesignKey]) AS [Value]
FROM [Design]
GROUP BY [Name];
But this will be fine if the table has only one value for DesignGroupId.
What do you need as a result for the other DesignGroupIds?
Maybe GROUP BY [DesignGroupId], [Name]:
SELECT
[DesignGroupId],
[Name] AS [Display],
MIN([DesignKey]) AS [Value]
FROM [Design]
GROUP BY [DesignGroupId], [Name];
Is your objective to get the minimum DesignKey value for each Name (Display) and Group? You can wrap your result into a minimum value outer query:
SELECT DISPLAY, MIN(VALUE) from (
SELECT
[D].[Name] AS [Display],
[D].[DesignKey] AS [Value]
FROM
[Design] AS [D]
JOIN
[DesignGroup] AS [DG] ON [D].[DesignGroupId] = [DG].[DesignGroupId]
GROUP BY
[D].[Name], [D].[DesignKey])
GROUP BY Display;

Oracle SQL - Select duplicates based on two columns

I need to select duplicate rows based on two columns in a join, and i can't seem to figure out how that is done.
Currently i got this:
SELECT s.name,administrative_site_id as adm_id,s.external_code,si.identifier_value
FROM suppliers s
INNER JOIN suppliers_identifier si
ON s.id = si.supplier_id
And the output is something along the lines of below:
| Name | adm_id | external_code |identifier_value |
|:-----------|------------:|:------------: |:----------------:|
| Warlob | 66323 | ext531 | id444 |
| Ozzy | 53123 | ext632 | id333 |
| Motorhead | 521 | ext733 | id222 |
| Perez | 123 | ext833 | id111 |
| Starlight | 521 | ext934 | id222 |
| Aligned | 123 | ext235 | id111 |
What i am looking for, is how to simply select these 4 rows, as they are duplicates based on column: adm_id and Identifier_value
| Name | adm_id | external_code |identifier_value |
|:-----------|------------:|:------------: |:----------------:|
| Motorhead | 521 | ext733 | id222 |
| Perez | 123 | ext833 | id111 |
| Starlight | 521 | ext934 | id222 |
| Aligned | 123 | ext235 | id111 |
First group by ADM_ID, IDENTIFIER_VALUE and find groups that has more than one row in it.
Then select all rows that has these couples
SELECT S.NAME
,ADMINISTRATIVE_SITE_ID AS ADM_ID
,S.EXTERNAL_CODE
,SI.IDENTIFIER_VALUE
FROM SUPPLIERS S INNER JOIN SUPPLIERS_IDENTIFIER SI ON S.ID = SI.SUPPLIER_ID
WHERE (ADMINISTRATIVE_SITE_ID, SI.IDENTIFIER_VALUE) IN (SELECT ADMINISTRATIVE_SITE_ID AS ADM_ID, SI.IDENTIFIER_VALUE
FROM SUPPLIERS S INNER JOIN SUPPLIERS_IDENTIFIER SI ON S.ID = SI.SUPPLIER_ID
GROUP BY ADM_ID, IDENTIFIER_VALUE
HAVING COUNT(*) > 1)
Or an alternate way that may perform better on big datasets:
with t as (
SELECT s.name,administrative_site_id as adm_id,s.external_code,si.identifier_value
COUNT(*) OVER (PARTITION BY administrative_site_id ,identifier_value ) AS cnt
FROM suppliers s
INNER JOIN suppliers_identifier si
ON s.id = si.supplier_id)
select name, adm_id, external_code, identifier_value
from t
where cnt > 1

Return 0 quantity when SKU not found

I have in my database 2 tables: warehouse and warehouse_inventory.
My warehouse table looks like:
name | warehouse_id |
--------+----------------|
name_1 | warehouse_id_1 |
name_2 | warehouse_id_2 |
name_3 | warehouse_id_3 |
My warehouse_inventory table looks like:
warehouse_id | SKU | quantity |
----------------+-------------+----------|
warehouse_id_1 | item_sku_1 | 100 |
warehouse_id_2 | item_sku_1 | 100 |
And now, I am looking for a solution which gets me result like this:
name | warehouse_id | SKU | quantity |
--------+-----------------------------+----------|
name_1 | warehouse_id_1 | item_sku_1 | 100 |
name_1 | warehouse_id_1 | item_sku_2 | 0 |
name_2 | warehouse_id_2 | item_sku_1 | 100 |
name_2 | warehouse_id_2 | item_sku_2 | 0 |
name_3 | warehouse_id_3 | item_sku_1 | 0 |
name_3 | warehouse_id_3 | item_sku_2 | 0 |
when I select with where condition in SQL query:
SELECT * FROM [what's here?] WHERE warehouse_inventory.SKU IN ('item_sku_1', 'item_sku_2')
You can't do this if you don't have a table with all the SKU you have on your database.
So, assuming that you have a table called [item] for all your item master data, you should do that:
SELECT W0.name, W0.warehouse_id, I0.SKU, ISNULL(W1.quatity, 0) as 'Quantity'
FROM [item] I0
CROSS JOIN [warehouse] W0
LEFT JOIN [warehouse_inventory] W1 ON W1.warehouse_id = W0.warehouse_id AND W1.SKU = I0.SKU
On SAP Business One we do this:
SELECT W0.WhsName, W0.WhsCode, I0.ItemCode, ISNULL(W1.OnHand, 0) as 'Quantity'
FROM OITM I0
CROSS JOIN OWHS W0
LEFT JOIN OITW W1 ON W1.WhsCode = W0.WhsCode AND W1.ItemCode = I0.ItemCode
ORDER BY 1 DESC
You can use CROSS JOIN with LEFT JOIN:
select w.name, w.warehouse_id, wii.SKU, coalesce(i.quantity, 0) as quantity
from warehouse w cross join
warehouse_inventory wii left join
warehouse_inventory i
on i.warehouse_id = w.warehouse_id and i.SKU = wii.SKU
order by w.name;

Using inner join twice

Trying to select the Match Table and convert the ID's into the Schools name, but right now I can only get one row to work at a time. What would my select look like instead?
select Match.ID, School, GuestTeamID from Match
inner join Team on team.id = match.HomeTeamID
Match Table
+------------+------------+-------------+
| ID | HomeTeamID | GuestTeamID |
+------------+------------+-------------+
| 1 | 1 | 2 |
| 2 | 3 | 4 |
+------------+------------+-------------+
Team Table:
+----+----------+
| ID | School |
+----+----------+
| 1 | School A |
| 2 | School B |
| 3 | School C |
| 4 | School D |
+----+----------+
Join Team table twice with Match table to fetch school name.
Try this:
SELECT M.ID, t1.School AS HomeSchool, t2.School AS GuestSchool
FROM MATCH m
INNER JOIN Team t1 ON t1.id = m.HomeTeamID
INNER JOIN Team t2 ON t2.id = m.GuestTeamID;