Sql query in Microsoft Access - ms-access

I have this query written in Microsoft Access:
SELECT p.artnbr AS [Number],
p.name AS Name,
s.sizename AS Sizes,
s.sizeindex AS SizeIndex,
s.oid AS SizeId,
l.name AS LocationName,
(SELECT od.quantity
FROM orderdetails od
WHERE od.ORDER = (SELECT o.oid
FROM [order] o
WHERE o.active = -1
AND o.location = l.oid)
AND od.productsize = s.oid) AS Quantity
FROM [size] AS s
INNER JOIN (product AS p
INNER JOIN (favorite AS f
INNER JOIN location AS l
ON f.customer = l.customer)
ON p.oid = f.product)
ON p.oid = s.product
WHERE f.customer = #customer
The link below shows tables i used and their relationships.
https://dl.dropbox.com/u/18377860/QueryTables.png
This query returns a correct result, but as u can see i am using a Sub query to get the quantity. I cant figure out how can i rewrite this query using join statements instead of that long sub-query. Any help would be appreciated.
Regards
EDIT: To make it more clear, my query needs to get all unique combinations of (product, size, location) whether they have an [Order] or not and display ordered quantity. If an order does not exist for a particular combination the quantity should be null.
EDIT2:
I managed to build the query and it looks like this:
SELECT p.ArtNbr AS [Number],
p.Name AS Name,
s.SizeName AS Sizes,
s.SizeIndex AS SizeIndex,
s.Oid AS SizeId,
l.Name AS LocationName,
so.qty AS Quantity
FROM ([Size] AS s
INNER JOIN (Product AS p
INNER JOIN (Favorite AS f
INNER JOIN Location AS l
ON f.Customer = l.Customer) ON p.OID = f.Product)
ON p.OID = s.Product)
LEFT JOIN
(SELECT od.ProductSize AS PS,
od.Quantity AS qty,
o.Location as Location
FROM OrderDetails AS od INNER JOIN [Order] AS o ON od.Order = o.OID
WHERE o.Active = -1) AS so ON so.PS = s.OID
WHERE f.Customer = #customer AND (l.OID = so.Location OR so.Location is null)
I did like Matt said, i moved the sub-query into the FROM section, i included ProductSize and Location in the select query of the derived table, then linking the result with "Size" table and i finally added a condition to the where section to eliminate the repetition of the same record for each Location.

I managed to build the query and it looks like this:
SELECT p.ArtNbr AS [Number],
p.Name AS Name,
s.SizeName AS Sizes,
s.SizeIndex AS SizeIndex,
s.Oid AS SizeId,
l.Name AS LocationName,
so.qty AS Quantity
FROM ([Size] AS s
INNER JOIN (Product AS p
INNER JOIN (Favorite AS f
INNER JOIN Location AS l
ON f.Customer = l.Customer) ON p.OID = f.Product)
ON p.OID = s.Product)
LEFT JOIN
(SELECT od.ProductSize AS PS,
od.Quantity AS qty,
o.Location as Location
FROM OrderDetails AS od INNER JOIN [Order] AS o ON od.Order = o.OID
WHERE o.Active = -1) AS so ON so.PS = s.OID
WHERE f.Customer = #customer AND (l.OID = so.Location OR so.Location is null)
I did like Matt said, i moved the sub-query into the FROM section, i included ProductSize and Location in the select query of the derived table, then linking the result with "Size" table and i finally added a condition to the where section to eliminate the repetition of the same record for each Location.

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.

Extracting latest version of articles from the results of a previous query

I have the following query:
SELECT e_c.*, c.name, j.status, j.version, j.articleId, j.title FROM assetcategory AS c
INNER JOIN assetentries_assetcategories AS e_c
ON c.categoryId = e_c.categoryId AND c.name = 'news'
INNER JOIN assetentry AS e
ON e.entryId = e_c.entryId
INNER JOIN journalarticle AS j
ON j.resourcePrimKey = e.classPK
AND e.classNameId = (SELECT classNameId FROM classname_ WHERE value = 'com.liferay.portlet.journal.model.JournalArticle')
AND j.companyId= e.companyId
WHERE j.status = 0
which returns all the category news in the journalarticles. From the results I need to select the most recent versions for each articleId. For example suppose there is an article with 4 versions, even with different title, it is the same article because it will have the same articleId. So therefore for each unique articleId I need the latest version. How can I do that?
Add a join to a subquery which finds the most recent version for each article:
SELECT e_c.*, c.name, j1.status, j1.version, j1.articleId, j1.title
FROM assetcategory AS c
INNER JOIN assetentries_assetcategories AS e_c
ON c.categoryId = e_c.categoryId AND c.name = 'news'
INNER JOIN assetentry AS e
ON e.entryId = e_c.entryId
INNER JOIN journalarticle AS j1
ON j1.resourcePrimKey = e.classPK AND
e.classNameId = (SELECT classNameId FROM classname_
WHERE value = 'com.liferay.portlet.journal.model.JournalArticle') AND
j.companyId = e.companyId
INNER JOIN
(
SELECT articleId, MAX(version) AS max_version
FROM journalarticle
WHERE status = 0
GROUP BY articleId
) j2
ON j1.articleId = j2.articleId AND j1.version = j2.max_version;
The basic idea behind the join to the subquery aliased as j2 above is that it restricts the result set to only the most recent version of each article. We don't necessarily have to change the rest of the query.

SQL - return rows that do not have a certain value

looking for a bit of help here if possible?
I have the following query:-
On or database we have a table called Linkfile, in this table are "Types" all beginning with "YG". I need to return those rows that do not have the type of "YG8" but just cannot seem to do it. I know ill need to use a sub query but am stuck!
This is my code and the fields I need to return. I just need to only show those that do not have the lk.type of "YG8"
select distinct l.description, p.displayname AS Temp, p.compliance_status As 'Compliant', lk.displayname, lk.type
from event e
inner join organisation o on e.organisation_ref = o.organisation_ref
inner join opportunity opp on e.opportunity_ref = opp.opportunity_ref
inner join event_role ev on ev.event_ref = e.event_ref
inner join address a on a.address_ref = opp.address_ref
inner join person p on ev.person_ref = p.person_ref
inner join lookup l on p.responsible_team = l.code
inner join person_type pt on p.person_ref = pt.person_ref
inner join linkfile lk on lk.parent_object_ref = pt.person_ref
where o.displayname LIKE '%G4S%' and p.compliance_category = '$016'
and lk.type like 'YG%' and l.code_type = '2'
and a.displayname LIKE '%MOJ%'
and pt.status = 'A'
order by l.description, p.displayname, lk.type
Use below query :
select distinct l.description, p.displayname AS Temp, p.compliance_status As 'Compliant', lk.displayname, lk.type,lk.parent_object_ref
from event e
inner join organisation o on e.organisation_ref = o.organisation_ref
inner join opportunity opp on e.opportunity_ref = opp.opportunity_ref
inner join event_role ev on ev.event_ref = e.event_ref
inner join address a on a.address_ref = opp.address_ref
inner join person p on ev.person_ref = p.person_ref
inner join lookup l on p.responsible_team = l.code
inner join person_type pt on p.person_ref = pt.person_ref
left join (select displayname, type,parent_object_ref from linkfile where lk.type like 'YG8%' )lk on lk.parent_object_ref = pt.person_ref
where o.displayname LIKE '%G4S%' and p.compliance_category = '$016' and lk.parent_object_ref is null
and l.code_type = '2'
and a.displayname LIKE '%MOJ%'
and pt.status = 'A'
order by l.description, p.displayname, lk.type;
I've used left join on linkfile with type like 'YG8%' and fetching the only records which are not matched
I think you can just replace the
lk.type like 'YG%'
with the following:
(lk.type >= 'YG' and lk.type <'YG8') or (lk.type > 'YG8' and lk.type <='YGZ')
this should accomplish what you are trying to do and also avoid using "like" which is less efficient (assuming you have an index on lk.type, at least).
You may refine this a bit by knowing which are the possible values of lk.type of course. I.e. what are the extremes for the YG "subtype"? YG00-YG99? YG-YGZ?
(Be especially careful if you may have YG81 or YG87 for example, because then my clause will not work properly... on the other hand if your YG subtype can have values like YG34 it would have been better to use YG08 instead of YG8)

I want to Query w3school database

The database is at: http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all . Particulary I want to get the list of customers who placed product orders on July 1996 from Speedy Express Shipping Company and were served by employees: Davolio Nancy and Peacock Margaret. The result should have:
Name of customer, contact, address, city, postal code and country
The orderDetailID they placed
Contacts of the shipping company
Product name, price and quantity
Product name, price and units bought
Category of the products
Here is my query:
SELECT
c.CustomerName,
c.ContactName,
c.Address,
c.City,
c.PostalCode,
c.Country,
o.OrderDetailID,
s.Phone,
r.ProductName,
r.Price,
o.Quantity,
g.CategoryName
FROM Customers c
JOIN Orders d
on (c.CustomerID = d.CustomerID)
LEFT JOIN OrderDetails o
on (o.OrderID = d.OrderID)
LEFT JOIN Shippers s
on (s.ShipperID = d.ShipperID)
LEFT JOIN Products r
on (r.ProductID = o.ProductID)
LEFT JOIN Categories g
on (g.CategoryID = r.CategoryID)
LEFT JOIN Employees e
on (e.EmployeeID = d.EmployeeID)
WHERE s.ShipperName = 'Speedy Express' AND
((e.LastName = 'Davolio' AND e.FirstName = 'Nancy') OR
(e.lastName = 'Peacock' AND e.firstName = 'Margaret')) AND
EXTRACT(YEAR_MONTH FROM d.OrderDate) = 199607;
I get error which says:
ERROR 1: Could not prepare statement (1 near "FROM": syntax error)
When I remove the last condition (of extracting the date) as follows:
SELECT c.CustomerName, c.ContactName, c.Address, c.City, c.PostalCode, c.Country, o.OrderDetailID, s.Phone, r.ProductName, r.Price, o.Quantity, g.CategoryName FROM Customers c JOIN Orders d on (c.CustomerID = d.CustomerID) LEFT JOIN OrderDetails o on (o.OrderID = d.OrderID) LEFT JOIN Shippers s on (s.ShipperID = d.ShipperID) LEFT JOIN Products r on (r.ProductID = o.ProductID) LEFT JOIN Categories g on (g.CategoryID = r.CategoryID) LEFT JOIN Employees e on (e.EmployeeID = d.EmployeeID) WHERE s.ShipperName = 'Speedy Express' AND((e.LastName = 'Davolio' AND e.FirstName = 'Nancy') OR (e.lastName = 'Peacock' AND e.firstName = 'Margaret'));
the error disappears. So please how can i fix the year_month condition without getting error!
One possibility here is that your version of MySQL, for whatever reason, does not support YEAR_MONTH being used with EXTRACT(). One workaround here would be to use DATE_FORMAT() instead:
WHERE DATE_FORMAT(d.OrderDate, '%Y%m') = '199607'
To test whether you have an old version of EXTRACT(), just try running the following simple query:
SELECT EXTRACT(YEAR_MONTH FROM NOW());
If this errors out, then my conjecture is correct.

Joining MYSQL queries problem

Above is my query ... but the corresponding names for the observer_ID and staff_ID is in another table called staff. SO some how i need to join (o.observer_ID=s.staff_ID) AND ( o.staff_ID=s.staff_ID) to get the two names of the observer and the person being observed (o.staff_ID). Please help me with it. Thanks
SELECT DISTINCT o.Room, o.Date,o.Module_code,o.observer_ID,o.staff_ID,o.form_id
FROM mbm2_db.observation_details as o,mbm2_db.Staff as s
WHERE o.date = '2011-08-09' and o.Module_code = 'IS5103'
SELECT DISTINCT
o.Room, o.Date,o.Module_code,o.observer_ID,o.staff_ID,o.form_id,
s1.name, s2.name
FROM
mbm2_db.observation_details AS o
LEFT JOIN mbm2_db.Staff AS s1 ON o.observer_ID = s1.staff_ID
LEFT JOIN mbm2_db.Staff AS s2 ON o.staff_ID = s2.staff_ID
WHERE
o.date = '2011-08-09' AND o.Module_code = 'IS5103'
Maybe a self inner join:
SELECT DISTINCT o.Room, o.Date,o.Module_code, o.observer_ID, o.staff_ID, o.form_id
FROM mbm2_db.observation_details As o
JOIN mbm2_db.Staff As s ON o.staff_ID = s.staff_ID
JOIN mbm2_db.Staff As b ON b.observer_ID = s.staff_ID
WHERE o.date = '2011-08-09' and o.Module_code = 'IS5103';
SELECT DISTINCT o.Room, o.Date,o.Module_code,o.observer_ID,o.staff_ID,o.form_id
FROM mbm2_db.observation_details o, mbm2_db.Staff s
WHERE o.date = '2011-08-09'
AND o.Module_code = 'IS5103'
AND o.staff_ID=s.staff_ID
AND o.observer_ID=s.staff_ID
SELECT DISTINCT o.Room, o.Date, o.Module_code, o.observer_ID, o.staff_ID, o.form_id
FROM (mbm2_db.observation_details AS o LEFT JOIN mbm2_db.Staff AS observer ON o.observer_ID = oberver.staff_ID)
LEFT JOIN mbm2_db.Staff AS observed ON o.staff_ID = observed.staff_ID
WHERE o.date = '2011-08-09' and o.Module_code = 'IS5103'
Tell me if it works (and check some values manually).