I have the following tables.
PHONES
- id
- name
- colour
- size
STOCK
- store_id
- phone_id
- instock
STORES
- id
- name
LINKS
- store_id
- phone_id
- url
I want to SELECT name, colour, size from PHONES, instock from STOCK, name from STORES, and url from LINKS WHERE stock.phone_id = phones.id = links.phone_id AND stock.store_id = links.store_id AND stores.id = stock.store_id.
I want out put, phone.name, phone.colour, phone.size, stock.instock, stores.name, links.url.
This is my current query. I am not getting specific links back related to that store AND phone id's.
SELECT DISTINCT(s.phone_id), st.name, st.logo_url, l.url, s.instock, s.datetime, p.model, p.colour, p.size
FROM stock AS s, stores AS st
INNER JOIN links AS l, phones AS p
WHERE s.phone_id = p.id
AND s.phone_id = l.phone_id
AND s.store_id = l.store_id
AND s.store_id IN ('3','4','5','6','8')
AND s.phone_id = '5'
ORDER BY datetime
DESC LIMIT 5
SELECT p.name, p.colour, p.size, st.instock, s.name, l.url
FROM phones p
INNER JOIN links l ON l.phone_id = p.id
INNER JOIN stores s ON s.id = l.store_id
INNER JOIN stock st ON st.store_id = s.id AND st.phone_id = p.id
WHERE s.id IN ('3', '4', '5', '6', '8')
AND p.id = '5'
datetime isn't defined in your table description so I neglected to add it to the query, but this should provide what you are looking.
Related
I need have created a select statement to list out all the customers that have been to multiple merchants below.
I want to create another statement to display how many of those customers have been to each merchant.
What is the optimal method of approaching this problem?
Lists out all customers that have been to multiple merchants.
WITH valentinesDayMerchant AS (
SELECT m.MerchantId, m.MerchantGroupId, m.WebsiteName
FROM Merchant m
INNER JOIN OpeningHours oh ON m.MerchantId = oh.MerchantId AND oh.DayOfWeek = 'TUE'
LEFT JOIN devices.DeviceConnectionState AS dcs ON dcs.MerchantId = oh.MerchantId
WHERE MerchantStatus = '-' AND (m.PrinterType IN ('V','O') OR dcs.State = 1 OR dcs.StateTransitionDateTime > '2023-01-23')
)
SELECT DISTINCT ul.UserLoginId, ul.FullName, ul.EmailAddress, ul.Mobile
FROM dbo.UserLogin AS ul
INNER JOIN dbo.Patron AS p ON p.UserLoginId = ul.UserLoginId
INNER JOIN valentinesDayMerchant AS m ON (m.MerchantId = ul.ReferringMerchantId OR m.MerchantId IN (SELECT pml.MerchantId FROM dbo.PatronMerchantLink AS pml WHERE pml.PatronId = p.PatronId AND ISNULL(pml.IsBanned, 0) = 0))
LEFT JOIN (
SELECT mg.MerchantGroupId, mg.MerchantGroupName, groupHost.HostName [GroupHostName]
FROM dbo.MerchantGroup AS mg
INNER JOIN dbo.Merchant AS parent ON parent.MerchantId = mg.ParentMerchantId
INNER JOIN dbo.HttpHostName AS groupHost ON groupHost.MerchantID = parent.MerchantId AND groupHost.Priority = 0
) mGroup ON mGroup.MerchantGroupId = m.MerchantGroupId
LEFT JOIN (
SELECT po.PatronId, MAX(po.OrderDateTime) [LastOrder]
FROM dbo.PatronsOrder AS po
GROUP BY po.PatronId
) orders ON orders.PatronId = p.PatronId
INNER JOIN dbo.HttpHostName AS hhn ON hhn.MerchantID = m.MerchantId AND hhn.Priority = 1
WHERE ul.UserLoginId NOT IN (1,2,100,372) AND ul.UserStatus <> 'D' AND (
ISNULL(orders.LastOrder, '2000-01-01') > '2020-01-01' OR ul.RegistrationDate > '2022-01-01'
)
GROUP BY ul.UserLoginId, ul.FullName, ul.EmailAddress, ul.Mobile
HAVING COUNT(m.MerchantId) > 1
Methods I have tried include adding the merchant name to a group by and displaying the count of the customers, however this does not work as I cannot have anything related to the Merchant in the GROUP BY, or I wouldn't be able to use HAVING clause to identify the customers that have been to multiple merchants. I have also tried selecting all the merchants and counting the distinct customers which doesn't work as it takes into account all the customers, not specifically the customers that have been to multiple merchants only.
I was trying to find out product counts with GROUP_BY on name
However These 2 queries confused me a bit.
How can the count of distinct products (Which is 204 -> Query-A) be higher than actual number of products (Which is single -> Query-B)?
Query-A
SELECT an.name
, COUNT(DISTINCT product.productid)
FROM product
JOIN productkeywords pk
ON product.productid = pk.productid
JOIN categorydisplayattributes cda
ON product.categoryid = cda.categoryid
JOIN attributenames an
ON cda.attributeid = an.attributeid
AND an.name = 'Number of Fixed Shelves'
WHERE pk.keywords LIKE '%mouse%'
GROUP
BY an.name
LIMIT 100
Output-A
name , COUNT(DISTINCT product.productid)
-------------------------+-------
'Number of Fixed Shelves', '204'
Query-B
SELECT an.name, product.productid FROM product
JOIN productkeywords pk ON product.productid = pk.productid
JOIN categorydisplayattributes cda ON product.categoryid = cda.categoryid
JOIN attributenames an ON cda.attributeid = an.attributeid AND an.name = 'Number of Fixed Shelves'
WHERE pk.keywords LIKE '%mouse%'
GROUP BY an.name
LIMIT 100
Output-B
name , productid
-------------------------+--------------
'Number of Fixed Shelves', '1025794284'
By adding the productid to the GROUP BY you ensure one output row per name/product combination.
By leaving it out you were only get one row per name. (And so it was being forced to pick one arbitrary productid from the list of 204 possible values.)
SELECT an.name, product.productid
FROM product
JOIN productkeywords pk ON product.productid = pk.productid
JOIN categorydisplayattributes cda ON product.categoryid = cda.categoryid
JOIN attributenames an ON cda.attributeid = an.attributeid
AND an.name = 'Number of Fixed Shelves'
WHERE pk.keywords LIKE '%mouse%'
GROUP BY an.name, product.productid
(You also want to remove the LIMIT if you want all 204 rows.)
Parent Table(Animals)
ID :
Name:
Sex :[Male=0 ,Female=1 ,other= -1,DESEXED - Female=2,DESEXED - Male =3]
Transaction Table
Transaction ID
Animal_Father_ID
Animal_Mother_ID
Animal_Child_ID
Date
Status
Sample Transaction
With Transaction table now I need to join parent table and needs to get the summary with Animal name like;
How I used select statement with joining Parent Table(Animals) And get above result ?
(previous developer create this structure and it's have almost 20GB data. Now I can't change the table structure)
SELECT TOP 1
t.ID,
p.Name as 'Name of Father',
m.Name as 'Name of Mother',
c.Name as 'Name if Child',
t.Date,
t.Status
FROM Transactions t
JOIN Animals m ON m.ID = t.Animal_Mother_ID
JOIN Animals p ON p.ID = t.Animal_Father_ID
JOIN Animals c ON c.ID = t.Animal_Child_ID
I am riffing off of koryakinp's answer, but adding in a case statement to transform the value of the status:
SELECT
t.Transaction_ID,
p.Name as 'Name of Father',
m.Name as 'Name of Mother',
c.Name as 'Name if Child',
t.Date,
CASE
WHEN t.Status = 1 THEN 'Active'
WHEN t.Status = 2 THEN 'Value2'
WHEN t.Status = 3 THEN 'Value3'
WHEN t.Status = 4 THEN 'Value4'
WHEN t.Status = 5 THEN 'Value5'
ELSE t.Status
END as Status
FROM transaction t
JOIN parent m ON m.ID = t.Animal_Mother_ID
JOIN parent p ON p.ID = t.Animal_Father_ID
JOIN parent c ON c.ID = t.Animal_Child_ID
and without the case statement:
SELECT
t.Transaction_ID,
p.Name as 'Name of Father',
m.Name as 'Name of Mother',
c.Name as 'Name if Child',
t.Date
FROM transaction t
JOIN parent m ON m.ID = t.Animal_Mother_ID
JOIN parent p ON p.ID = t.Animal_Father_ID
JOIN parent c ON c.ID = t.Animal_Child_ID
This is my situation.
I have 3 tables
Orders
- id status deleted
Order Lines
- related_id related_model quantity
Products
- id code price price_purchase
I want to create a list with all products. The amount of times they are purchased and a sum of the gross margin (price - price_purchase). It must only use orders lines with the related model set to 'products'. And secondly it must only pick orders with the status set to 'paid, processing, sent, ready_for_pickup or picked_up' and with the order not deleted.
So this would be the result I want:
id | code | purchases | value
-------------------------------
1 | code1 | 7 | 57,05
2 | code2 | 122 | 254,98
3 | code3 | 0 | 0,00
This is the SQL query I have so far:
SELECT p.id, p.code, IFNULL(SUM(sol.quantity) , 0) as purcahses,
sum((p.price - p.price_purchase) * quantity) as value
FROM products p
LEFT JOIN shop_orders_lines sol ON sol.related_id = p.id
AND sol.related_model = 'products'
LEFT JOIN shop_orders so ON so.id = sol.order_id
WHERE so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up')
AND so.deleted = 0
GROUP BY p.id
It returns the correct data. But not all problems. That is my problem. I a lot of different methods like sub queries and other methods but can't seem to solve the problem. I know the problem is my LEFT join, but don't know a solution to my problem.
I'm using MySQL Workbench.
Any help is welcome.
Your joins are wrong. You need to identify the order lines to consider separately from and prior to forming the LEFT JOIN with the product details. An inline view could help:
SELECT
p.id,
p.code,
IFNULL(SUM(ordered_item.quantity) , 0) as purchases ,
sum((p.price - p.price_purchase) * ordered_item.quantity) as value
FROM
products p
LEFT JOIN (
SELECT
sol.related_id AS related_id,
sol.quantity AS quantity
FROM
shop_orders_lines sol
INNER JOIN shop_orders so
ON so.id = sol.order_id
WHERE
so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up')
AND so.deleted = 0
AND sol.related_model = 'products'
) ordered_item
ON ordered_item.related_id = p.id
GROUP BY p.id
Move outer table conditions from WHERE to ON, otherwise the OUTER JOIN works like a regular INNER JOIN:
SELECT p.id, p.code, IFNULL(SUM(sol.quantity) , 0) as purcahses,
sum((p.price - p.price_purchase) * quantity) as value
FROM products p
LEFT JOIN shop_orders_lines sol ON sol.related_id = p.id
AND sol.related_model = 'products'
LEFT JOIN shop_orders so ON so.id = sol.order_id AND
so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up')
AND so.deleted = 0
GROUP BY p.id
Is p.id the whole primary key for that table? If not, you need to find out how to treat p.code. (Either list in GROUP BY, or use as argument to aggregate function.)
Another try:
SELECT p.id, p.code, IFNULL(SUM(sol.quantity) , 0) as purcahses,
sum((p.price - p.price_purchase) * quantity) as value
FROM products p
JOIN shop_orders_lines sol ON sol.related_id = p.id
AND sol.related_model = 'products'
WHERE EXISTS (select 1 from shop_orders so
where so.id = sol.order_id
AND so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up')
AND so.deleted = 0)
GROUP BY p.id
I'm struggling with an problem to make a query of the following:
I have an table called Article_Statuses (and the main table Articles, with ArticleID as p.key) and has the following structure
ID, ArticleID, Status, Status_Date, Category
In this table I collect all the statuses of the articles (ArticleID) per category (which are predefined), the highest ID per category is the latest status of that category, herewith some data:
1, BB0001, LFS, 15-01-2015, LIC
2, BB0001, LFA, 19-01-2015, LIC
3, BB0001, SA, 10-01-2015, FIS
4, BB0001, CA, 19-01-2015, FIS
5, BB0002, LFS, 10-01-2015, LIC
6, BB0002, LFA, 11-01-2015, LIC
7, BB0003, CA, 19-01-2015, FIS
I want to make a query with the following result:
ArticleID, Status LIC, Status_Date LIC, Status FIS, Status_Date FIS
BB0001, LFA, 19-01-2015, CA, 19-01-2015
BB0002, LFA, 11-01-2015, ,
BB0003, , , CA, 19-01-2015
I found the following solution which works for only one category, I'm stuck with adding the other categories...
SELECT `a`.`ArticleID`, `b`.`Status_Date` AS `LIC_Date`, `b`.`Status` AS `LIC_Status`
FROM `Articles` `a`
INNER JOIN `Article_Statuses` `b` ON `a`.`ArticleID` = `b`.`ArticleID`
INNER JOIN ( SELECT `ArticleID`, MAX( `ID` ) `MAXID`
FROM `Article_Statuses`
WHERE `Category` = 'LIC' GROUP BY `ArticleID` ) `c`
ON `b`.`ArticleID` = `c`.`ArticleID` AND `b`.`ID` = `c`.`MAXID`
WHERE `a`.`Partner` = 10
GROUP BY `a`.`ArticleID`
ORDER BY `a`.`ArticleID` ASC
What is the meaning of "Partner" in your query? You didn't mentioned it anywhere earlier so I'm guessing it's not important.
How many different categories do you have? Just two or more? I'm asking because returning data in such a way is far for being fast and optimal.
It would be something like:
SELECT
a.ArticleID,
b.Status_Date AS LIC_Date, b.Status AS LIC_Status,
d.Status_Date AS FIS_Date, d.Status AS FIS_Status
FROM Articles AS a
INNER JOIN Article_Statuses AS b ON a.ArticleID = b.ArticleID
INNER JOIN (
SELECT ArticleID, MAX( ID ) AS ID
FROM Article_Statuses
WHERE Category = 'LIC' GROUP BY ArticleID
) AS c ON b.ArticleID = c.ArticleID AND b.ID = c.ID
INNER JOIN Article_Statuses AS d ON a.ArticleID = d.ArticleID
INNER JOIN (
SELECT ArticleID, MAX( ID ) AS ID
FROM Article_Statuses
WHERE Category = 'FIS' GROUP BY ArticleID
) AS e ON d.ArticleID = e.ArticleID AND d.ID = e.ID
WHERE a.Partner = 10
ORDER BY a.ArticleID ASC
Basically you repeat joins just with different aliased - I used "d" and "e" but it's better to use something meaningful like "LIC_category" instead of just "b".
You also should use left join instead of inner join if some categories can be empty as in your example.
This is the query which returns desired result:
select a.articleid,
b.status_date as LIC_Date, b.status as LIC_Status,
c.status_date as FIS_Date, c.status as FIS_Status
from Articles a
left join Article_Statuses b on b.ArticleID =a.articleid and
b.id = (select max(id) from Article_Statuses ast
where ast.articleid=a.articleid and ast.category='LIC')
left join Article_Statuses c on c.ArticleID =a.articleid and
c.id = (select max(id) from Article_Statuses ast
where ast.articleid=c.articleid and ast.category='FIS')
order by a.articleid
I used left joins because not for every article both categories are present.