Oracle SQL Return Count of Primary key from 2 different columns in the same table - sql

Tables
ARMASTER = Customer Information
ORDERHEAD = Sales order information (Ship to, bill to)
Hey everyone! I'm still quite new to SQL and I do belive I'm picking it up fairly quick. I have been racking my brain on this for a few hours now and have asked around the office and nobody seems to have a solution.
I'm trying to identify how many times a customer account has been used as a SHIP TO location & a BILL TO location.
SELECT ARMASTER.CUSTOMER,
ARMASTER.DIVISION,
ARMASTER.STATUS,
ARMASTER.CUHEAD AS "MASTER",
COUNT (ORDERHEAD.BILLTO) AS "COUNT_BILL",
COUNT (ORDERHEAD.SHIPTO) AS "COUNT_SHIP"
FROM ARMASTER
LEFT OUTER JOIN ORDERHEAD
ON ARMASTER.CUSTOMER = ORDERHEAD.BILLTO
LEFT OUTER JOIN ORDERHEAD
ON ARMASTER.CUSTOMER = ORDERHEAD.SHIPTO
GROUP BY ARMASTER.CUSTOMER,
ARMASTER.DIVISION,
ARMASTER.STATUS,
ARMASTER.CUHEAD
And I'm not even remotley getting what I should be getting. However, when I remove one of my joins the count is exactly what it should be for either 1 or the other of them.
Any guidance would be muchly appreciated! Thank you!

I think it can also work
SELECT CUSTOMER,
DIVISION,
STATUS,
CUHEAD AS "MASTER",
(SELECT COUNT(1) FROM ORDERHEAD WHERE SHIPTO = ARMASTER.CUSTOMER ) AS "COUNT_BILL",
(SELECT COUNT(1) FROM ORDERHEAD WHERE BILLTO = ARMASTER.CUSTOMER ) AS "COUNT_SHIP"
FROM ARMASTER

Related

SQL - join three tables based on (different) latest dates in two of them

Using Oracle SQL Developer, I have three tables with some common data that I need to join.
Appreciate any help on this!
Please refer to https://i.stack.imgur.com/f37Jh.png for the input and desired output (table formatting doesn't work on all tables).
These tables are made up in order to anonymize them, and in reality contain other data with millions of entries, but you could think of them as representing:
Product = Main product categories in a grocery store.
Subproduct = Subcategory products to the above. Each time the table is updated, the main product category may loses or get some new suproducts assigned to it. E.g. you can see that from May to June the Pulled pork entered while the Fishsoup was thrown out.
Issues = Status of the products, for example an apple is bad if it has brown spots on it..
What I need to find is: for each P_NAME, find the latest updated set of subproducts (SP_ID and SP_NAME), and append that information with the latest updated issue status (STATUS_FLAG).
Please note that each main product category gets its set of subproducts updated at individual occasions i.e. 1234 and 5678 might be "latest updated" on different dates.
I have tried multiple queries but failed each time. I am using combos of SELECT, LEFT OUTER JOIN, JOIN, MAX and GROUP BY.
Latest attempt, which gives me the combo of the first two tables, but missing the third:
SELECT
PRODUCT.P_NAME,
SUBPRODUCT.SP_PRODUCT_ID, SUBPRODUCT.SP_NAME, SUBPRODUCT.SP_ID, SUPPRODUCT.SP_VALUE_DATE
FROM SUBPRODUCT
LEFT OUTER JOIN PRODUCT ON PRODUCT.P_ID = SUBPRODUCT.SP_PRODUCT_ID
JOIN(SELECT SP_PRODUCT_ID, MAX(SP_VALUE_DATE) AS latestdate FROM SUBPRODUCT GROUP BY SP_PRODUCT_ID) sub ON
sub.SP_PRODUCT_ID = SUBPRODUCT.SP_PRODUCT_ID AND sub.latestDate = SUBPRODUCT.SP_VALUE_DATE;
Trying to find a row with a max value is a common SQL pattern - you can do it with a join, like your example, but it's usually more clear to use a subquery or a window function.
Correlated subquery example
select
PRODUCT.P_NAME,
SUBPRODUCT.SP_PRODUCT_ID, SUBPRODUCT.SP_NAME, SUBPRODUCT.SP_ID, SUPPRODUCT.SP_VALUE_DATE,
ISSUES.STATUS_FLAG, ISSUES.STATUS_LAST_UPDATED
from PRODUCT
join SUBPRODUCT
on PRODUCT.P_ID = SUBPRODUCT.SP_PRODUCT_ID
and SUBPRODUCT.SP_VALUE_DATE = (select max(S2.SP_VALUE_DATE) as latestDate
from SUBPRODUCT S2
where S2.SP_PRODUCT_ID = SUBPRODUCT.SP_PRODUCT_ID)
join ISSUES
on ISSUES.ISSUE_ID = SUBPRODUCT.SP_ID
and ISSUES.STATUS_LAST_UPDATED = (select max(I2.STATUS_LAST_UPDATED) as latestDate
from ISSUES I2
where I2.ISSUE_ID = ISSUES.ISSUE_ID)
Window function / inline view example
select
PRODUCT.P_NAME,
S.SP_PRODUCT_ID, S.SP_NAME, S.SP_ID, S.SP_VALUE_DATE,
I.STATUS_FLAG, I.STATUS_LAST_UPDATED
from PRODUCT
join (select SUBPRODUCT.*,
max(SP_VALUE_DATE) over (partition by SP_PRODUCT_ID) as latestDate
from SUBPRODUCT) S
on PRODUCT.P_ID = S.SP_PRODUCT_ID
and S.SP_VALUE_DATE = S.latestDate
join (select ISSUES.*,
max(STATUS_LAST_UPDATED) over (partition by ISSUE_ID) as latestDate
from ISSUES) I
on I.ISSUE_ID = S.SP_ID
and I.STATUS_LAST_UPDATED = I.latestDate
This often performs a bit better, but window functions can be tricky to understand.

SQL Query Daily Sales Per Month of a specific product

I've got a query which gets the lists of customers who've made a purchase of the product for the current day
select Customer.customerName, sum(InvoiceDetail.itemPrice * InvoiceDetail.itemQuantity) as dailyPurchase from Invoice
inner join InvoiceDetail on Invoice.invoiceID = InvoiceDetail.invoiceID
inner join Customer on Invoice.customerID = Customer.customerID
inner join Item on InvoiceDetail.itemID = Item.itemID
inner join Branch on Branch.branchID = Invoice.branchID
inner join Region on Region.regionID = Branch.regionID
where
Invoice.inactive = 0 and InvoiceDetail.inactive = 0
and Item.itemTypeID = 3
and Region.regionCode = 'CR'
and cast(Invoice.invoiceDate as date) = convert(date, '01/08/2016', 103)
group by Customer.customerName
What I need is a table with a list of all the dates in the current month, listing ALL customers who have at least purchased the product ONCE. It should resemble something similar to this image here.
Any help on how to get started or a general idea of how to get the desired result, is much appreciated. Thanks!
Sample Data from Results:
customerName dailyPurchase
AGH COMMUNICATIONS 450.00
ARIEL AMARCORD SHOP 285.00
AKN COMMUNICATION 300.00
AWSDAC TELECOMMUNICATION 2850.00
BARLEY MOBILE & SERVICES 285.00
Table Structure - I'm sorry, I don't know an easier way to copy this.
First get the customers who have purchased the product atleast once this month alongwith date.
Then use pivot to get the result in the form that you want (as seen in image). Search stackoverflow for pivot in sql server, you will get good info.
Give some information about the table structure and sample data and I might be able to help you with the query to get the results.

MS Access SQL left join giving all 0

I am trying to make a summary table of all the items I have. I have a raw data table with 10 users who respectively have different items. There are maximum 3 different items and I want to do a count to see how many items each individual has. The following is my code.
Select b.Country,b.UserID,Num_including_fruits, Apple,Orange
from
(((SELECT o.Country,o.UserID, IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID))
AS Num_including_fruits
FROM [SEA2_View] as o
GROUP BY o.UserID, o.Country
ORDER BY Country)as b
LEFT JOIN
(SELECT o.Country,o.UserID,IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID)
AS Apple
FROM [APAC2_View] as o
WHERE o.fruit_status <>"fresh" AND o.HWType = "Apple"
GROUP BY o.Country,o.UserID)as d
ON (b.UserID = d.UserID))
LEFT JOIN
(SELECT o.Country,o.UserID,IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID))
AS Orange
FROM [SEA2_View] as o
WHERE o.fruit_status <>"fresh" AND o.HWType = "Orange"
GROUP BY o.Country,o.UserID)as e
ON (d.UserID = e.UserID))
;
The first join returns the correct result but the second join somehow returns all 0, which is incorrect. Therefore please help! and I would appreciate any advice for best practice when it comes to joins in SQL. Thanks lot!
Are you sure you don't have a table naming error?
You're first joining [SEA2_View] with [APAC2_View]. The second join is joining with [SEA2_View] with itself.

SQL LEFT JOIN WHERE not displaying right result

So I got this query:
Data structure:
Users
id---inlog----name----more stuff
llntoets
id---code----inlog----more stuff
oefeningen
id---speler---status----morestuff
(inlog and speler are always the same values for a user)
SELECT
// Some other stuff working
SUM(o.status) AS oefn
FROM users AS u
LEFT JOIN llntoets AS l
ON (u.inlog = l.inlog)
LEFT JOIN oefeningen AS o
ON (u.inlog = o.speler) AND o.status = 'afgewerkt'
WHERE
code = '$code'
GROUP BY l.inlog
ORDER BY klas ASC, klasnr ASC
Everything runs fine except 1 thing the oefn variable. It shows a number sometimes it shows the correct value and sometimes it shows a value that is much higher than it should be. Someone told me it could be because of the GROUP BY. Can someone help me pls?
It is supposed to count the total records from table oefeningen where status = 'afgewerkt' and where the speler is the inlog from users. Thanks, if you got other questions ask will try to explain more.
the SUM(o.status) in your query it is not supposed to count the total records of table oefeningen.
that sum is the sum of the values of all the joined rows that satisfy your criteria that can be a much higher number.
also note that applying the filter o.status = 'afgewerkt' you are performing a JOIN even if you wrote LEFT JOIN throghout the query.

Access data source using SQL to show most recent entry per site

First of all I am a complete beginner to SQL and have been thrown in at the deep end a bit ! I'm learning as I go along and each mistake I make or question I ask will hopefully help me develop... please be kind :)
I have a working query that extracts electricty meter readings and other information. I am after finding the most recent reading for each site. This is the query at the moment :
PARAMETERS [Site Group] Text ( 255 );
SELECT
Lookup.Lookup_Name AS [Group],
Contacts.Name AS Site,
Points.Number AS MPAN,
Max(DataElectricity.Date) AS MaxDate,
DataElectricity.M1_Present,
DataElectricity.M2_Present,
DataElectricity.M3_Present,
DataElectricity.M4_Present,
DataElectricity.M5_Present,
DataElectricity.M6_Present,
DataElectricity.M7_Present,
DataElectricity.M8_Present,
DataElectricity.Direct
FROM
DataElectricity INNER JOIN (Lookup INNER JOIN (Points INNER JOIN Contacts ON Points.Contacts_Id = Contacts.Id) ON Lookup.Lookup_Id = Contacts.Group_1) ON DataElectricity.Point_Id = Points.Id
WHERE
((DataElectricity.Direct)='D')
GROUP BY
Lookup.Lookup_Name, Contacts.Name, Points.Number, DataElectricity.M1_Present, DataElectricity.M2_Present, DataElectricity.M3_Present, DataElectricity.M4_Present, DataElectricity.M5_Present, DataElectricity.M6_Present, DataElectricity.M7_Present, DataElectricity.M8_Present, DataElectricity.Direct
ORDER BY
Lookup.Lookup_Name, Contacts.Name, Max(DataElectricity.Date) DESC;
However this returns all the readings for a site rather than just the most recent... I'm sure this is simple but I can't figure it out.
Any advice or guidence is gratefully received :)
Can't you just use top 1 to get only the first result?
SELECT top 1 ...
I have evolved the code a bit further using caspian's suggestion of SELECT top 1... but am struggling to refine it further and produce the result I need.
PARAMETERS [Site Group] Text ( 255 );
SELECT
Lookup.Lookup_Name,
Contacts.Name AS Site,
Points.Number AS MPAN,
DataElectricity.M1_Present,
DataElectricity.M2_Present,
DataElectricity.M3_Present,
DataElectricity.M4_Present,
DataElectricity.M5_Present,
DataElectricity.M6_Present,
DataElectricity.M7_Present,
DataElectricity.M8_Present,
DataElectricity.Direct
FROM
(
SELECT TOP 1 DataElectricity.Date AS MaxDate,
DataElectricity.M1_Present,
DataElectricity.M2_Present,
DataElectricity.M3_Present,
DataElectricity.M4_Present,
DataElectricity.M5_Present,
DataElectricity.M6_Present,
DataElectricity.M7_Present,
DataElectricity.M8_Present,
DataElectricity.Point_id
FROM
DataElectricity
ORDER BY MaxDate DESC
)
DataElectricity INNER JOIN (Lookup INNER JOIN (Points INNER JOIN Contacts ON Points.Contacts_Id = Contacts.Id) ON Lookup.Lookup_Id = Contacts.Group_1) ON DataElectricity.Point_Id = Points.Id
WHERE
((Lookup.Lookup_Name)=Lookup_Name)
ORDER BY
Lookup.Lookup_Name, Contacts.Name, MaxDate DESC;
I do have a Google Drive file showing a small example of the data tables and desired result with hopfully a clear guide as to how the tables connect.
https://docs.google.com/file/d/0BybrcUCD29TxWVRsV1VtTm1Bems/edit?usp=sharing
The actual data contains hundreds of Site Groups each with potentially hundreds of sites.
I would like my end users to be able to select the Site Group name from the Lookup.Lookup_Name list and for it to return all the relevant sites and readings.
.... I really hope that makes sense !