SQL Server Concatenate Rows Using Many-To-Many Related Tables - sql

I've already searched for my problem, but most of the examples (if not all), have to deal with only one or two tables with a one-to-many relationship between them.
So, here goes my scenario:
My first table is:
OrderID Quantity Price
----------------------------------
18 1000.00 160.00
19 1000.00 40.00
22 1000.00 40.00
23 100.00 500.00
24 10.00 50.00
My second table is:
ExtrasID Name
-------------------
1 Value 1
2 Value 2
3 Value 3
4 Value 4
5 Value 5
I have a many-to-many relationship established between the tables above, so there is a third (joint) table which is as follows:
OrderExtrassID OrderExtras_OrderID OrderExtras_ExtrasID
----------------------------------------------------------------
20 19 2
22 22 3
23 23 2
24 23 5
Now, all I want to achieve is to get a result such as the following:
OrderID Extras
----------------------------
18 NULL
19 Value 2
22 Value 3
23 Value 2, Value 5
24 NULL
There are many examples using XML PATH, PIVOT, CTE etc., but none of these seems to help me with my scenario, or at least I've not managed to study them in depth, in order to get my work done...
Thanks in advance,

I would suggest using For XML to return multiple rows into a single row and then using STUFF to removing the extra comma. Something like this:
SELECT O.OrderId
,STUFF(
(
SELECT ',' + E.Name AS [text()]
FROM OrderExtras OE
Inner Join Extras E
ON E.ExtrasId = OE.OrderExtras_ExtrasID
WHERE O.OrderId = OE.OrderExtras_OrderID
ORDER BY E.Name
FOR XML PATH('')
), 1, 1, '') AS ColList
FROM Orders O
And here is the SQL Fiddle.
Good luck.

Related

How to get the LATEST value for each sellerID for each productID

At the company where I work we buy the same products from different sellers according to who offers us the better price, and to make the purchase decisions easier I'd like a query that would tell me for each productId, what's the latest price recorded for each seller iD.
I have a table that looks something like this.
purchaseId
productId
price
sellerId
date
1
1
23
1
2021-01-13
2
2
20
1
2021-01-13
3
1
33
2
2021-01-19
4
3
55
2
2021-01-19
5
2
25
1
2021-01-23
6
1
19
3
2021-01-23
7
1
22
1
2021-01-26
8
2
29
2
2021-01-29
I'd like the query to return a table like this, with a column for each sellerID:
productId
priceSellerID1
priceSellerId2
priceSellerId3
1
22
33
19
2
25
19
NULL
3
NULL
55
NULL
There are and could be more and more sellers, this is just a small example.
I want to pull this information to fill a DataGridView in a winforms app, what I thought of first was to populate the DGV with the productIds, and then, for each row pull the information with a query like this for each sellerId:
SELECT price FROM purchase_details
WHERE productId = #productID AND date = (SELECT MAX(DATE) FROM purchase_details WHERE productId = #productID and sellerId = #sellerId)
This takes lot of time to fill in the dgv for just a few ids, so I know it's just not the right way, but unfortunately I can't wrap my head around a query that would gather this information efficiently.
Any information would be greatly appreciated, and if there's way I could improve the question I'd like to know too. Thanks.
Seems like you're looking for Dynamic SQL with a little twist. The subquery src will select the last record per productID and SellerID ordered by date
Example
Declare #SQL varchar(max) ='
Select *
From (
Select top 1 with ties
productID
,Item = concat(''priceSellerID'',sellerId)
,Value = price
From #YourTable
Order by row_number() over (partition by productID,SellerID order by date desc)
) src
Pivot (min([Value]) For [Item] in (' + stuff((Select Distinct ','+QuoteName(concat('priceSellerID',sellerId))
From #YourTable
For XML Path('')),1,1,'') + ') ) p
'
Exec(#SQL);
Results

Custom SQL queries in Directus

Let's say I have this kind of MySQL database structure :
Menu :
id name
3 Tartiflette
4 Lasagne
Ingredient :
id name price
15 Carrot 2.00
39 Garlic 3.00
40 Reblochon 5.00
55 Onion 1.00
Menu_ingredient :
id ingredient_id menu_id quantity
4 15 4 2
5 55 4 1
6 39 4 1
7 40 3 2
8 55 3 3
Resa_menu :
id resa_id menu_id people
1 1 4 3
2 1 3 2
Resa :
id
1
How could I get all the ingredients from one reservation, using one query parameter with the items/ endpoint ?
I tried the query using items/resa_menu?fields=*.* (and some other combinations, but out of luck).
I also set up an SQL View (virtual table) getting all info needed with a query, but this kind of SQL doesn't seem to be fetched by Directus.
SELECT
ingredient.name as ing_name,
(resa_menu.people * ingredient.price) as price,
(resa_menu.people * menu_ingredient.quantity) as quantity
FROM resa_menu
INNER JOIN menu ON menu.id = resa_menu.menu_id
INNER JOIN resa ON resa.id = resa_menu.resa_id
INNER JOIN menu_ingredient ON menu_ingredient.menu_id = menu.id
INNER JOIN ingredient ON ingredient.id = menu_ingredient.ingredient_id
GROUP BY ingredient.id;
Expected output :
ing_name price quantity
Carrot 6.00 6
Garlic 9.00 3
Reblochon 10.00 4
Onion 3.00 3
The specific goal here is to get a summary of all ingredients needed for the reservation (combining all menus, multiplying quantity by number of people). But my question is more generic on : how can you do multiple JOINs like in this query with Directus API ?
Many thanks for the help!
I think what you mean is you're requesting the endpoint /items/Resa_menu and doing *.* is returning Menu_ingredient related data, however you would like a list of ingredients returned too? for this, would you not just change your fields query to *.*.* to get three levels of relations?
Or is it that the ?fields=*.* simply isn't working at all?
use left join and you does not need group by
select i.name,(i.price* coalesce(rm.people,1)) as price,
(mi.quantity*coalesce(rm.people,1)) as quantity
from Ingredient i left join
Menu_ingredient mi on i.id =mi.ingredient_id
left join Resa_menu rm on mi.menu_id =rm.menu_id

How do I make a query that selects where the SUM equals a fixed value

I've spent that last couple of days searching for a way to make a SQL query that searches the database and returns records where the SUM of the same ID's equal or grater then the value provided.
For this I've been using the W3schools database to test it out in the products table.
More so what I've been trying to do:
SELECT * FROM products
WHERE supplierid=? and SUM(price) > 50
in the "where supplier id" would loop through same suppliers and sum of their price higher than 50 in this case return the records.
In this case it would read supplier ID 1 then add the price of all that supplier 18+19+10=47 now 47 < 50 so it will not print those records at the end. Next supplier ID 2 22+21.35=43.35 and again would not print those records until the sum of price is higher than 50 it will print
I'm working with a DB2 database.
SAMPLE data:
ProductID ProductName SupplierID CategoryID Price
1 Chais 1 1 18
2 Chang 1 1 19
3 Aniseed 1 2 10
4 Chef Anton 2 2 22
5 Chef Anton 2 2 21.35
6 Grandma's 3 2 25
7 Uncle Bob 3 7 30
8 Northwoods 3 2 40
9 Mishi 4 6 97
10 Ikura 4 8 31
11 Queso 5 4 21
12 Queso 5 4 38
13 Konbu 6 8 6
14 Tofu 6 7 23.25
How about:
select * from products where supplierid in (
select supplierid
from products
group by supplierid
having sum(price) > 50
);
The subquery finds out all the supplierid values that match your condition. The main (external) query retrieves all rows that match the list of supplierids.
not tested, but I would expect db2 to have analytic functions and CTEs, so perhaps:
with
basedata as (
select t.*
, sum(t.price) over(partition by t.supplierid) sum_price
from products t
)
select *
from basedata
where supplierid = ?
and sum_price > 50
The analytic function aggregates the price information but does not group the resultset, so you get the rows from your initial result, but restricted to those with an aggregated price value > 50.
The difference to a solution with a subquery is, that the use of the analytic function should be more efficient since it has to read the table only once to produce the result.

inserting sql with loop

I have the table PERSONAL
ID_PERS NAME
---------------
11 azerty
22 uiop
and the table TOURNE_LABEL
ID_TOUR NAME
--------------
1 w
2 p
3 v
I want to loop over all of person and then join it with tourne and insert to a new table.
I have created empty table LS_PDA
ID_PERS ID_TOURN
-------------------
11 1
11 2
11 3
22 1
22 2
22 3
how can I do that ?
SQL is all about set based operations. If you're thinking about a loop, chances are you're heading in the wrong direction. For this problem, you could cross-join the tables, thus producing all the possible combinations, and use the insert-select syntax:
INSERT INTO ls_pda
SELECT id_pres, id_tour
FROM personal
CROSS JOIN tourne_label

T-SQL - Getting a list of records depending on other related records values

I'm trying to make a query and need a little help (SQL Server).
Imagine the following scenario: user is viewing a web page which has several related categories. According to some rules, the page should not be displayed if a specific category has been put together with another category.
For this I've got 2 tables:
1) Has the page Id and the related categories:
Pk CategoryNumber
--------------------
1 30
1 31
1 45
2 30
3 21
3 26
3 64
4 25
4 12
5 25
5 31
5 30
5 45
2) Rules table. First row means: when viewing a page with the category 30 it should not be retrieved if it also has the 45 category.
WhenViewingCategoryNumber HideEverythingWithCategoryNumber
-------------------------------------------------------
30 45
25 31
Output expected:
2
3
4
I've spent a few hours around this and I'm not going anywhere, so I would appreciate if someone could help. If possible, would be better an answer with a SELECT statement to integrate it directly within a larger CTE statement. Many thanks.
You can use the following query to identify those page ids related to conflicting categories:
SELECT DISTINCT c1.PageId
FROM Categories AS c1
INNER JOIN Rules AS r ON c1.ItemNumber = r.WhenViewingCategoryNumber
INNER JOIN Categories AS c2 ON c1.PageId = c2.PageId
AND r.HideEverythingWithCategoryNumber = c2.ItemNumber
This will return:
PageId
------
1
5
Now you can get expected result by simply using NOT IN:
SELECT DISTINCT PageId
FROM Categories
WHERE PageId NOT IN ( ... above query here ....)
Demo here