Joining two views on id AND date not working - sql

Situation thus far
I have two tables sales_orders and purchase_orders which contain id, company_id and inserted_at each.
I created two views sales_orders_view and purchase_orders_view which truncate the timestamp to that week's monday (using the date_trunc function) and count the orders entered by each company. So my sales_order_view and purchase_order_view look like this:
What I am trying to accomplish
I am trying to join the two views to create a data set which looks as follows:
This is what I am doing:
SELECT
so.company_id,
so.week_of,
so.sales_orders,
po.purchase_orders
FROM
sales_orders_view so
INNER JOIN
purchases_orders_view po
ON so.company_id = po.company_id
GROUP BY
so.company_id,
so.week_of,
sales_orders,
purchase_orders
The numbers I get back as a result are completely out of whack and I can't figure out for the life of me what I am doing wrong.
Would really appreciate some help.
Thanks!

No aggregation is needed. Just include the week in the ON clause:
SELECT so.company_id, so.week_of, so.sales_orders,
po.purchase_orders
FROM sales_orders_view so INNER JOIN
purchases_orders_view po
ON so.company_id = po.company_id AND so.week_of = po.week_of;
Note: This only returns weeks that are in both tables for a given company. If you want all weeks where there are no matches, then you need an outer join of some sort.

Related

Record with latest date, where date comes from a joined table

I have tried every answer that I have found to finding the last record, and I have failed in getting a successful result. I currently have a query that lists active trailers. I am needing it to only show a single row for each trailer entry, where that row is based on a date in a joined table.
I have tables
trailer, company, equipment_group, movement, stop
In order to connect trailer to stop (which is where the date is), i have to join it to equipment group, which joins to movement, which then joins to stop.
I have tried using MAX and GROUP BY, and PARTITION BY, both of which error out.
I have tried many solutions here, as well as these
https://thoughtbot.com/blog/ordering-within-a-sql-group-by-clause
https://www.geeksengine.com/article/get-single-record-from-duplicates.html
It seems that all of these solutions have the date in the same table as the thing that they want to group by, which I do not.
SELECT
trailer.*
company.name,
equipment_group.currentmovement_id,
equipment_group.company_id,
movement.dest_stop_id, stop.location_id,
stop.*
FROM trailer
LEFT OUTER JOIN company ON (company.id = trailer.company_id)
LEFT OUTER JOIN equipment_group ON (equipment_group.id =
trailer.currenteqpgrpid)
LEFT OUTER JOIN movement ON (movement.id =
equipment_group.currentmovement_id)
LEFT OUTER JOIN stop ON (stop.id = movement.dest_stop_id)
WHERE trailer.is_active = 'A'
Using MAX and GROUP BY gives error "invalid in the select list... not contained in...aggregate function"
Welllllll, I never did end up figuring that out, but if I joined movements on to equipment group by two conditions, all is well. Each extra record was created by each company id.... company id is in EVERY table.

join to all rows of a table even without values sql server

I have a date table that I use to determine week of the year (our year is not calendar year based right now.). I have a union query that creates a table that I am going to use in a table valued function. I can create the table in the union query but it only produces the 40 weeks that have actual data. I need it to show the weeks regardless of whether data exists or not.
I have tried to left outer join on the week table but I still get only records where the week has data associated with it.
left outer join [dbo].[LOOKUP_WEEK_NUMBER] w on
(p.[Program_Year_ID] = w.[Program_Year_Nbr]) and
(p.[Installation_Complete_Date] between w.[Week_Start] and w.[Week_End])
LOOKUP_WEEK_NUMBER table has all the weeks of the year and a start and end date for each week. The p table contains the project data. What I am doing is bucketing the projects into weeks for reporting purposes.
Can anyone point me in the right direction? Thanks in advance.
change to a left join from your lookup table instead of to your lookup table, or use a right join to your lookup table.
from [dbo].[LOOKUP_WEEK_NUMBER] w
left join ... p
on (p.[Program_Year_ID] = w.[Program_Year_Nbr])
and (p.[Installation_Complete_Date] between w.[Week_Start] and w.[Week_End])

SQL: If there is No match on condition (row in table) return a default value and Rows which match from different tables

I have three tables: Clinic, Stock and StockLog.
I need to get all rows where Stock.stock < 5. I need to also show if an order has been placed and what amount it is; which is found in the table Stocklog.
The issue is that a user can set his stock level in the Stock table without placing an order which would go to Stocklog.
I need a query that can : return the rows in the Stock table and get the related order amounts in the Stocklog table. If no order has been placed in StockLog, then set amount to order amount to zero.
I have tried :
SELECT
Clinic.Name,
Stock.NameOfMedication, Stock.Stock,
StockLog.OrderAmount
FROM
Clinic
JOIN
Stock ON Stock.ClinicID = Clinic.ClinicID
JOIN
StockLog ON StockLog.StockID = Stock.StockID
WHERE
Stock.Stock <= 5
The issue with my query is that I lose rows which are not found in StockLog.
Any help on how to write this.
Thank you.
I am thinking the query should look like this:
SELECT c.Name, s.NameOfMedication, s.Stock,
COALESCE(sl.OrderAmount, 0) as OrderAmount
FROM Stock s LEFT JOIN
Clinic c
ON s.ClinicID = c.ClinicID LEFT JOIN
StockLog sl
ON sl.StockID = s.StockID
WHERE s.Stock <= 5 ;
You want to keep all rows in Stock (subject to the WHERE condition). So think: "make Stock the first table in the FROM and use LEFT JOIN for all the other tables."
If you want to keep all the rows that result from joining Clinic and Stock, then use a LEFT OUTER JOIN with StockLog. I don't know which SQL you're using (SQL Server, MySQL, PostgreSQL, Oracle), so I can't give you a precise example, but searching for "left outer join" in the relevant documentation should work.
See this Stack Overflow post for an explanation of the various kinds of joins.

Merge 2 columns from different SQL server table with empty lines

I have this query to achieve my goal:
SELECT
Datum, LeavetypeID
FROM
Kalender
INNER JOIN
VerlofLijn ON Kalender.ID = VerlofLijn.DagID
WHERE
VerlofLijn.Persnummer = #pnummer;
So basically I have a calendar in the table Kalender.
Every day has a unique id(Kalender.ID). In a second table (VerlofLijn) the matching Kalender.ID is stored in VerlofLijn.DagID, together with the leavetype and the unique employee number Persnummer.
What I want to achieve is a query that loads all dates from the calendar, and - if the current logged-on employee has leave in the database - show this next to the correct date.
So if there is no leave at all in the database for this employee, I still need the calendar to show up so in a next step he can add leave to his personal calendar.
I could create a personal calendar for every employee, but there has to be a better way, without the overhead of storing way to much data in the database, which will make the query to take much more time to search and complete.
Please try this query
SELECT
Datum, LeavetypeID
FROM
Kalender
LEFT JOIN
VerlofLijn
ON Kalender.ID = VerlofLijn.DagID AND VerlofLijn.Persnummer = #pnummer;
Explanation: As you mentioned
i want to achieve is a query that loads all dates from the calendar
you should use Kalender LEFT JOIN VerlofLijn
Have you tried LEFT OUTER JOIN like this?
SELECT
Datum, LeavetypeID
FROM
Kalender
LEFT OUTER JOIN
VerlofLijn ON Kalender.ID = VerlofLijn.DagID
WHERE
VerlofLijn.Persnummer = #pnummer;
You get all the values from Kalendar even if there are no matches from the table VerlofLijn, and all the common values from VerlofLijn.
You can find some examples here: What is the difference between "INNER JOIN" and "OUTER JOIN"?

SQL Syntax for Complex Scenario (Deals)

i have a complex query to be written but cannot figure it out
here are my tables
Sales --one row for each sale made in the system
SaleProducts --one row for each line in the invoice (similar to OrderDetails in NW)
Deals --a list of possible deals/offers that a sale may be entitled to
DealProducts --a list of quantities of products that must be purchased in order to get a deal
now im trying to make a query which will tell me for each sale which deals he may get
the relevant fields are:
Sales: SaleID (PK)
SaleProducts: SaleID (FK), ProductID (FK)
Deals: DealID (PK)
DealProducts: DealID(FK), ProductID(FK), Mandatories (int) for required qty
i believe that i should be able to use some sort of cross join or outer join, but it aint working
here is one sample (of about 30 things i tried)
SELECT DealProducts.DealID, DealProducts.ProductID, DealProducts.Mandatories,
viwSaleProductCount.SaleID, viwSaleProductCount.ProductCount
FROM DealProducts
LEFT OUTER JOIN viwSaleProductCount
ON DealProducts.ProductID = viwSaleProductCount.ProductID
GROUP BY DealProducts.DealID, DealProducts.ProductID, DealProducts.Mandatories,
viwSaleProductCount.SaleID, viwSaleProductCount.ProductCount
The problem is that it doesn't show any product deals that are not fulfilled (probably because of the ProductID join). i need that also sales that don't have the requirements show up, then I can filter out any SaleID that exists in this query where AmountBought < Mandatories etc
Thank you for your help
I'm not sure how well I follow your question (where does viwSaleProductCount fit in?) but it sounds like you will want an outer join to a subquery that returns a list of deals along with their associated products. I think it would go something like this:
Select *
From Sales s Inner Join SaleProducts sp on s.SaleID = sp.SaleID
Left Join (
Select *
From Deals d Inner Join DealProducts dp on d.DealID = dp.DealId
) as sub on sp.ProductID = sub.ProductID
You may need to add logic to ensure that deals don't appear twice, and of course replace * with the specific column names you'd need in all cases.
edit: if you don't actually need any information from the sale or deal tables, something like this could be used:
Select sp.SaleID, sp.ProductID, sp.ProductCount, dp.DealID, dp.Mandatories
From SaleProducts sp
Left Join DealProducts as dp on sp.ProductID = dp.ProductID
If you need to do grouping/aggregation on this result you will need to be careful to ensure that deals aren't counted multiple times for a given sale (Count Distinct may be appropriate, depending on your grouping). Because it is a Left Join, you don't need to worry about excluding sales that don't have a match in DealProducts.