MYSQL GROUP_CONCAT and half dosen JOINs - mysql

I have been trying to get this query to work but I am stumbed right now.
Problem is on the JOIN with GROUP_CONCAT in it. I just can't figure how to get it working.
What I want is to get buntch of data from RFQs and joining Customers, etc. to it and everything was fine until I had to change Suppliers field so that it could have multiple suplliers per one RFQs row. I created new tables RFQsSuppliers where I combine Supplier.ID's and RFQs.ID's and I have table Suppliers that contains the names and other stuff.
I want to get Suppliers to have all suppliers separated with ','.
My Query:
$result = mysql_query("SELECT Pullero.DateAdded as DateAdded,
Customers.Name as customer,
Pullero.ID as RFQID,
Ships.Name as ship,
Pullero.CustomerRef as CustomerRef,
Contacts.FirstName as contactF,
Contacts.LastName as contactL,
Contacts.Email as contactE,
Users.tunnus as handler,
RFQStatus.Name as status,
Pullero.Description as RFQDescription,
Pullero.LastEdited as LastEdit
FROM RFQs Pullero
JOIN (SELECT RFQs.ID,
GROUP_CONCAT(Supplier.Name) AS Suppliers
FROM RFQs
LEFT JOIN RFQsSuppliers ON RFQs.ID = RFQsSuppliers.RFQID
JOIN Suppliers ON RFQsSuppliers.SupplierID = Suppliers.ID
GROUP BY RFQs.ID)
RFQsSuppliers ON Pullero.ID = RFQsSuppliers.RFQID
LEFT JOIN Ships ON RFQ.ShipID=Ships.ID
LEFT JOIN Contacts ON RFQ.ContactID=Contacts.ID
LEFT JOIN Customers ON RFQ.CustomerID=Customers.idCustomers
LEFT JOIN Users ON RFQ.PriJobHandler=Users.id
LEFT JOIN RFQStatus ON RFQ.StatusID=RFQStatus.ID
WHERE RFQs.LastEdited > '$lastedited'
ORDER BY RFQs.LastEdited ASC
") or die(mysql_error());
At the moment, error is :Unknown column 'Supplier.Name' in 'field list'
EDIT
Below is some expample of my Table desing:
RFQs
ID | DateAdded | CustomerID | ShipID | LastEdited | StatusID ...
/* -------------------------------------- */
Suppliers
ID | Name | CountryID
1 Sup1 2
2 Sup2 5
3 Sup3 3
4 Sup4 3
/* -------------------------------------- */
RFQsSuppliers
ID | RFQID | SupplierID
1 1 4
2 2 3
3 56 3
4 4 3
5 39 1
6 56 1
7 4 4
I tried to get only the suppliers with following query:
$result = mysql_query("SELECT Suppliers.Name as Suppliers
FROM RFQs
LEFT JOIN RFQsSuppliers ON RFQs.ID=RFQsSuppliers.SupplierID
LEFT JOIN Suppliers ON RFQsSuppliers.SupplierID=Suppliers.ID
GROUP BY RFQs.ID
") or die(mysql_error());
But print_r on each row returns only following:
Array ( [Suppliers] => Sup1,Sup1 ) Array ( [Suppliers] => ) Array ( [Suppliers] => Sup4,Sup4 ) Array ( [Suppliers] => ) Array ( [Suppliers] => ) Array ( [Suppliers] => )
Any ideas?

JOIN (
SELECT RFQs.ID,
GROUP_CONCAT(Supplier**s**.Name) AS Suppliers
FROM RFQs
LEFT JOIN RFQsSuppliers ON RFQs.ID = RFQsSuppliers.RFQID
JOIN Suppliers ON RFQsSuppliers.SupplierID = Suppliers.ID
GROUP BY RFQs.ID
) RFQsSuppliers
Try that
I believe you missed an 's' in your GROUP_CONCAT table name as you had it as Supplier.Name instead of Suppliers.name as per the table
Edit
Additionally you are referring to RFQs.LastEdited in WHERE and ORDER BY clauses however you aliased table RFQs to be named Pullero, so those will need changing to Pullero.LastEdited
Edited edit Reformatted to use JOINs instead of SUBQUERY
SELECT
Pullero.DateAdded as DateAdded,
Customers.Name as customer,
Pullero.ID as RFQID,
GROUP_CONCAT(Suppliers.Name) AS Suppliers,
Ships.Name as ship,
Pullero.CustomerRef as CustomerRef,
Contacts.FirstName as contactF,
Contacts.LastName as contactL,
Contacts.Email as contactE,
Users.tunnus as handler,
RFQStatus.Name as status,
Pullero.Description as RFQDescription,
Pullero.LastEdited as LastEdit
FROM RFQs AS Pullero
LEFT JOIN RFQsSuppliers ON RFQsSuppliers.RFQID = Pullero.ID
LEFT JOIN Suppliers ON RFQSuppliers.SupplierID = Suppliers.ID
LEFT JOIN Ships ON RFQ.ShipID=Ships.ID
LEFT JOIN Contacts ON RFQ.ContactID=Contacts.ID
LEFT JOIN Customers ON RFQ.CustomerID=Customers.idCustomers
LEFT JOIN Users ON RFQ.PriJobHandler=Users.id
LEFT JOIN RFQStatus ON RFQ.StatusID=RFQStatus.ID
WHERE Pullero.LastEdited > '$lastedited'
ORDER BY Pullero.LastEdited ASC
Or for an example using original subquery, the RFQs link seems superfulous so I've adjusted it + have added the Suppliers list into the output
$result = mysql_query("SELECT Pullero.DateAdded as DateAdded,
RFQsSuppliers.Suppliers,
Customers.Name as customer,
Pullero.ID as RFQID,
Ships.Name as ship,
Pullero.CustomerRef as CustomerRef,
Contacts.FirstName as contactF,
Contacts.LastName as contactL,
Contacts.Email as contactE,
Users.tunnus as handler,
RFQStatus.Name as status,
Pullero.Description as RFQDescription,
Pullero.LastEdited as LastEdit
FROM RFQs Pullero
JOIN (
SELECT RFQsSuppliers.RFQID,
GROUP_CONCAT(Suppliers.Name) AS Suppliers
FROM RFQsSuppliers.RFQID
JOIN Suppliers ON RFQsSuppliers.SupplierID = Suppliers.ID
GROUP BY RFQsSuppliers.RFQID
) AS RFQsSuppliers ON Pullero.ID = RFQsSuppliers.RFQID
LEFT JOIN Ships ON RFQ.ShipID=Ships.ID
LEFT JOIN Contacts ON RFQ.ContactID=Contacts.ID
LEFT JOIN Customers ON RFQ.CustomerID=Customers.idCustomers
LEFT JOIN Users ON RFQ.PriJobHandler=Users.id
LEFT JOIN RFQStatus ON RFQ.StatusID=RFQStatus.ID
WHERE Pullero.LastEdited > '$lastedited'
ORDER BY Pullero.LastEdited ASC
") or die(mysql_error());
EDIT Updated query for second part of question
$result = mysql_query("SELECT RFQs.ID, GROUP_CONCAT(Suppliers.Name) as Suppliers
FROM RFQs
LEFT JOIN RFQsSuppliers ON RFQs.ID=RFQsSuppliers.RFQID
LEFT JOIN Suppliers ON RFQsSuppliers.SupplierID=Suppliers.ID
GROUP BY RFQs.ID
") or die(mysql_error());

You're referencing the column Supplier.Name, but the table join is on a table called Suppliers, plural.
(SELECT RFQs.ID,
/* Should be plural Suppliers.Name here... */
GROUP_CONCAT(Suppliers.Name) AS Suppliers
FROM RFQs
LEFT JOIN RFQsSuppliers ON RFQs.ID = RFQsSuppliers.RFQID
JOIN Suppliers ON RFQsSuppliers.SupplierID = Suppliers.ID
GROUP BY RFQs.ID)
Later, in your final WHERE clause, you reference RFQs, however you have aliased that table as Pullero:
FROM RFQs Pullero
Change the WHERE clause to use
WHERE Pullero.LastEdited > '$lastedited'
ORDER BY Pullero.LastEdited ASC

Related

Is there a method of counting an attribute that is in a GROUP BY clause?

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.

SQL Query - Count inside GROUP BY no result

I want to count the patient diagnosis per municipality and consultation per municipality:
so it should be:
diagnosis per municipality + consultation per municipality
SELECT COUNT(consultations.id) +
(SELECT COUNT(patientdiagnosis.id)
FROM consultations
LEFT JOIN patientdiagnosis
ON patientdiagnosis.consultation_id = consultations.id
LEFT JOIN patients
ON consultations.patient_id = patients.id
LEFT JOIN rcitymun
ON patients.municipality = rcitymun.citycode
/*GROUP BY PER MUNICIPALITY SHOULD BE HERE*/
) as encounters, rcitymun.cityname
FROM consultations
LEFT JOIN patients
ON consultations.patient_id = patients.id
LEFT JOIN rcitymun
ON patients.municipality = rcitymun.citycode
GROUP BY patients.municipality;
current output:
encounters municipality
10323 BATAC
10423 NUEVA ERA
the encounter data is huge because it's counting all of the diagnosis instead of per municipality
what i want is to count the diagnosis per municipality.
desired output is something like this:
encounters municipality
105 BATAC
70 NUEVA ERA
It may be possible to reduce this by one subquery, but often it is best to start with independently grouped subqueries.
SELECT
rcitymun.cityname
, SUM(c.consult_count) consult_count
, SUM(d.diag_count) diag_count
FROM patients
INNER JOIN rcitymun ON patients.municipality = rcitymun.citycode
LEFT JOIN (
SELECT
consultations.patient_id
, COUNT(*) consult_count
FROM consultations
GROUP BY
consultations.patient_id
) c ON patients.id = c.patient_id
LEFT JOIN (
SELECT
consultations.patient_id
, COUNT(*) diag_count
FROM consultations
INNER JOIN patientdiagnosis ON patientdiagnosis.consultation_id = consultations.id
GROUP BY
consultations.patient_id
) d ON patients.id = d.patient_id
GROUP BY
rcitymun.cityname

MySQL Join 3 Tables with Count, Group & Where/Having Clause

I have 3 tables
TABLE ii_ProductCategory
-------------------
id title
TABLE ii_Product2Category
-------------------
categoryId productId
TABLE ii_Product
----------------
id minPrice
I want to find all Categories are either not contained in ii_Product2Category at all or are only linked to products that have minPrice IS NULL.
Here is my attempt. I am getting a GROUP BY ERROR.
SELECT COUNT(DISTINCT p2c.`categoryId`) as "ProdCount",
cat.`id`,
cat.`title`,
prod.`minPrice`
FROM `ii_ProductCategory` cat
LEFT JOIN `ii_Product2Category` p2c
ON p2c.`categoryId` = cat.`id`
LEFT JOIN `ii_Product` prod
ON p2c.`productId` = prod.`id`
WHERE prod.`minPrice` IS NULL
AND COUNT(DISTINCT p2c.`categoryId`) = 0
GROUP BY cat.`id`
I tried moving the prod.minPrice IS NULL to a HAVING on the join but that didn't work either. I also want to be able to drop the AND COUNT(DISTINCT p2c.categoryId) = 0 and sort by ProdCount so I can see total numbers of products in each whether they are null or not.
It doesn't make sense to not grouping the non-aggregated columns.
SELECT COUNT(DISTINCT p2c.`categoryId`) as "ProdCount",
cat.`id`,
cat.`title`,
prod.`minPrice`
FROM `ii_ProductCategory` cat
LEFT JOIN `ii_Product2Category` p2c
ON p2c.`categoryId` = cat.`id`
LEFT JOIN `ii_Product` prod
ON p2c.`productId` = prod.`id`
WHERE prod.`minPrice` IS NOT NULL
GROUP BY cat.`id`, cat.`title`, prod.`minPrice`
HAVING COUNT(DISTINCT p2c.`categoryId`) = 0

MYSQL - Union SELECT & GROUP BY Not working

I have 3 table, log, member, also guest, but my log i stored as customer(user)'s id only, which is either their guest_id or member_id. So here's the problem, because they're from different table, I'm not sure how to join & group together their data.
checkout_log table
id user_id checkout_as
--------------------------------------
1 1 member
2 2 guest
members table
id fullname
--------------------------------------
1 member01
2 member02
guests table
id fullname
--------------------------------------
1 guest01
2 guest02
What I wanted to Achieve - Result
id user_id fullname checkout_as
----------------------------------------------
1 1 member01 member
2 2 guest02 guest
Had tried following sql statement with UNION ALL, or GROUP BY , but had no luck.
SELECT * FROM
(
SELECT checkout_log.id,checkout_log.user_id,guests.fullname,guests.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN guests ON checkout_log.user_id = guests.id
UNION ALL
SELECT checkout_log.id,checkout_log.user_id,members.fullname,members.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN members ON checkout_log.user_id = members.id
) derivedTable
GROUP BY id
Try doing this with joins instead of union
select cl.id, cl.user_id,
coalesce(m.fullname, g.fullname) as fullname,
cl.checkout_as
from checkout_log cl left join
members m
on cl.user_id = m.id and cl.checkout_as = 'member' left join
guests g
on cl.user_id = g.id and cl.checkout_as = 'guest';

Do not bring a line of tables

Alright, let's to business ...
say I have a category (categoyid) '150 ', and would not bring anything that is in that category .....
It turns out that an article may be in multiple categories, and the more I block 150 in the category SELECT, it will still come to be linked to other categories ....
How do I, so that any item in the category '150 'is not sought in the SELECT even though he was also in another category than the '150' ...
Tables:
node
nodeid
contentid
url
publishdate
nodeinfo
nodeid
title
node_category
categoryid
nodeid
article
contentid
previewimage
=====================
I tried :
SELECT p.nodeid, p.contentid p.publishdate, p.url, c.categoryid, c.nodeid, a.previewimage, a.contentid, e.title FROM `node` AS p
INNER JOIN `nodecategory` AS c ON p.`nodeid` = c.`nodeid`
INNER JOIN `article` AS a ON p.`contentid` = a.`contentid`
INNER JOIN `nodeinfo` AS e ON p.`nodeid` = e.`nodeid`
WHERE c.`categoryid`
IN (73,74,77,105,71,70,72,76,100,80,79,78,81,108,145,146,82,142,83,97,153)
GROUP BY c.nodeid
ORDER BY p.`publishdate`
DESC LIMIT 4
I think you need a not-exists clause:
AND NOT EXISTS (
SELECT 1
FROM
`nodecategory` AS ic
WHERE
p.`nodeid` = ic.`nodeid`
AND ic.`categoryid` IN (150)
)
Here it is in your query, reformatted a bit:
SELECT
p.nodeid,
p.contentid,
p.publishdate,
p.url,
c.categoryid,
c.nodeid,
a.previewimage,
a.contentid,
e.title
FROM
`node` AS p
INNER JOIN `nodecategory` AS c ON p.`nodeid` = c.`nodeid`
INNER JOIN `article` AS a ON p.`contentid` = a.`contentid`
INNER JOIN `nodeinfo` AS e ON p.`nodeid` = e.`nodeid`
WHERE c.`categoryid`
IN (73,74,77,105,71,70,72,76,100,80,79,78,81,108,145,146,82,142,83,97,153)
AND NOT EXISTS (
SELECT 1
FROM
`nodecategory` AS ic
WHERE
p.`nodeid` = ic.`nodeid`
AND ic.`categoryid` IN (150)
)
GROUP BY c.nodeid
ORDER BY p.`publishdate`
DESC LIMIT 4
This should filter out nodes that are in one of the chosen categories, but are not also in those specified in the not-exists clause.