Combining tables in SQL (only for for certain rows) - sql

I wasn't even sure how to word this in the subject line. However, I have a SELECT statement that pulls information from an SQL view called CONTACTS (F_ame, L_Name, Address, Email, etc...). I have another view called INVOICES with purchase information for the members in the contacts view. Keep in mind that the INVOICES view has mulitple purchases of varying products for each member. These two views can be linked with a ContactID key
I only need to display a certain product (EADP Package), if purchased, from the INVOICES view on the same line as the member who purchased it. I also need to retain the entire member list in the pull. So, if I use a WHERE clause to only pull that product, It only gives me those who purchased that product. I need to keep the entire member list and still have a column that displays that particular product for those who purchased it. Hope that made sense.
Sorry, but there are 3 views, not 2. Here is what I have so far:
SELECT Contact.FirstName, Contact.LastName, Contact.CFSDesignation, Contact.EMailAddress1, Contact.Telephone1, Contact.DefaultPriceLevelIdName
FROM Contact INNER JOIN
FilteredInvoice ON Contact.ContactId = FilteredInvoice.contactid INNER JOIN
FilteredInvoiceDetail ON FilteredInvoice.invoiceid = FilteredInvoiceDetail.invoiceid
WHERE (Contact.DefaultPriceLevelIdName = 'member') AND FilteredInvoiceDetail.productidname = 'eAudiology 2014 Unlimited On-Demand Package'
This works fine,but only pulls those who purchased the package. I need the entire member list from CONTACTS (about 10,000 records) plus the product column showing the product above for those who purchased it. I belive is has something to do with joins, but can't get my head around it.
Getting Close, but it doesn't like the keyword "ON":
Also. in your previous answer, what are "C" and "I" used for?
SELECT Contact.FirstName, Contact.LastName, Contact.CFSDesignation, Contact.EMailAddress1, Contact.Telephone1, Contact.DefaultPriceLevelIdName
FROM Contact LEFT JOIN
FilteredInvoice ON Contact.ContactId = FilteredInvoice.contactid LEFT JOIN (SELECT FilteredInvoiceDetail.productidname
FROM FilteredInvoiceDetail
WHERE productidname = 'eAudiology 2014 Unlimited On-Demand Package') ON FilteredInvoice.invoiceid = FilteredInvoiceDetail.invoiceid
WHERE (Contact.DefaultPriceLevelIdName = 'member')

SELECT *
FROM Contacts C
LEFT JOIN ( SELECT *
FROM Invoices
WHERE Product = 'EADP Package') I
ON C.ContactID = I.ContactID

This finally worked for me:
SELECT DISTINCT Contact.ContactId,Contact.FirstName, Contact.LastName, Contact.CFSDesignation, Contact.EMailAddress1, Contact.DefaultPriceLevelIdName, productidname
FROM Contact LEFT JOIN
FilteredInvoice ON Contact.ContactId = FilteredInvoice.contactid LEFT JOIN (SELECT FilteredInvoiceDetail.productidname, FilteredInvoiceDetail.invoiceid
FROM FilteredInvoiceDetail
WHERE productidname = 'eAudiology 2014 Unlimited On-Demand Package' OR productidname = 'eAudiology 2014 Unlimited On-Demand Pkg Renewal') I ON FilteredInvoice.invoiceid = I.invoiceid
WHERE (Contact.DefaultPriceLevelIdName = 'member' OR DefaultPriceLevelIdName = 'student')
ORDER BY LastName

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.

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

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

SSRS 2008 R2 / SQL - How to filter groups but keep detail data?

EDIT - i'm reposting this question in an attempt to explain what i mean better
I'm using SQL 2008 R2 and I work for a retail department store and we need a report to show all the sales orders made in each department, and sections of those departments.
What i want is to group up all the sales order lines by department and section, but remove only the sections that have a total sales value of less than £50. I still want to see order lines that are over £50, though.
Here is an example of what i currently have:
Data before filtering
I want to remove the Accessories section and all lines contained within it, as it has a total section value of less than £50. So i would want it looking like this after filtering:
Data after filtering
Here is my code:
SELECT department.department_name
,section.section_name
,sales_order_detail.sales_order_number
,sales_order_detail.sales_order_line
,LineValue
FROM
sales_order_detail INNER JOIN stock_item ON sales_order_detail.stock_item_code = stock_item.stock_item_code
INNER JOIN style ON stock_item.style_code = style.style_code
INNER JOIN department ON style.dept_code = department.department_code
INNER JOIN section ON style.section_code = section.section_code AND style.dept_code = section.department_code AND department.department_code = section.department_code
Can you please explain all the ways this can be done. I've tried using GROUP BY and HAVING but that then filters out all my sales order lines. I've tried using a Group Filter in the visual studio report design surface which removes the lines but then aggregates calculated at the Department group scope don't take into account the lines removed at the section level.
I appreciate any help i can get on this.
Jacob
As you are using 2008R2, you can use the magic that are Windowed Functions to calculate the total of the group that the row belongs to (the partition part of the over clause below) and then wrap your query into a filtering select statement. Not having your data this is obviously not tested, but it should work:
select department_name
,section_name
,sales_order_number
,sales_order_line
,LineValue
,GroupTotal
from(
select d.department_name
,se.section_name
,sod.sales_order_number
,sod.sales_order_line
,sod.qty_ordered * sod.selling_price AS LineValue
,sum(sod.qty_ordered * sod.selling_price) over (partition by d.department_name
,se.section_name
) as GroupTotal
from sales_order_detail sod
inner join stock_item si
on sod.stock_item_code = si.stock_item_code
inner join style s
on stock_item.style_code = s.style_code
inner join department d
on s.dept_code = d.department_code
inner join section se
on s.section_code = se.section_code
and s.dept_code = se.department_code
and d.department_code = se.department_code
) a
where GroupTotal > 50

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.

How to return 1st record from group by

Trying to return only the 1st supplier code and have all other fields unaffected.
`Select
Container.Part_Key,
Part.Part_No,
Part.Name,
Part.Revision,
Container.Quantity,
Container.Container_Status,
OP.Operation_No,
Opp.Operation_Code,
Part.Part_Status,
Supplier.Supplier_Code
From Part_v_Container as Container
Join Part_v_Part as Part
ON Part.Part_Key = Container.Part_Key
Join Part_v_Part_Operation as Op
On Op.Part_Operation_Key = Container.Part_Operation_Key
Join Part_v_Operation as OPP
On OPP.Operation_Key = OP.Operation_Key
Join part_v_approved_supplier as Approved
On Approved.part_key = container.part_key
Join common_v_Supplier as Supplier
On Supplier.supplier_no = Approved.Supplier_No
Where Container.Active = '1'
group by container.part_key`
There will be duplicate part numbers, revisions, etc. Not worried about that. I just want the part no to list only one approved supplier to the far right, even though for any given part, there are multiple approved suppliers listed in the database.
Furthermore, the order the database lists the approved suppliers does not matter.
Thanks!
Add a sub query in your select list
( select top 1 supplier.supplier_code
From supplier
Where Supplier.supplier_no = Approved.Supplier_No order by Supplier.supplier_no) as supplier code
This can be the last field in the select list
You could add An appropriate order by.
This would work in SQL Server