JOINS in SQL using AdWorks Example - sql-server

I'm practicing using AdventureWorks and here's the question:
How many Sales Orders (Headers) used Vista credit cards in October 2002
SELECT * FROM Sales.SalesOrderHeader --a
SELECT * FROM Sales.CreditCard --b
SELECT
SUM(a.OrderDate), b.CardType
FROM
[Sales].[CreditCard] b
LEFT OUTER JOIN
[Sales].[SalesOrderHeader] a
I'm not sure how to write this query. I'm new to SQL and this is my first JOIN. Eyes are red...thanks

There are several issues:
You cannot sum dates. You have to use count here.
You must not use an outer join here. Use an inner join. The reason is that you only want SalesOrderHeaders that also have a corresponding CreditCard
You forgot the where clause
A join needs an on condition
select count(*) from
CreditCard cc inner join SalesOrderHeader so on cc.Id = so.CreditCardId
where cc.CardType = 'Visa' and so.OrderDate between '2002-10-01' and '2002-10-31'
I guessed the names of the foreign key fields cc.Id and so.CreditCardId because you didn't indicate this piece of information.

Related

Insert Into TABLE from 3 separate tables

I am getting my face kicked in....
I have a total of 4 tables
1. Business (BusinessID, CustomerID, BusName, Territory)
2. Customer (CustomerID, Name)
3. Sales (BusinessID, CustomerID, Territory, Jan, Feb, Mar, Apr, May, Jun)
4. Performance (this is the table I want the info in)
I've already created the table to have the following columns, BusinessID, CustomerID, BusName, Name, Territory, Jan,Feb,Mar,Apr,May,Jun
Every time I try to insert its not properly joining and I am getting a bunch of errors "multi-part identifier could not be bound"
insert into Performance (BusinessID, CustomerID, BusName, Name, Territory, January2018, February2018, March2018, April2018, May2018, June2018)
select Business.BusinessID, Customer.CustomerID, Business.BusName, Customer.Name, Sales.Territory, Sales.January2018, Sales.February2018, Sales.March2018, Sales.April2018, Sales.May2018, Sales.June2018
from Business A
inner join Customer B ON a.CustomerID = b.CustomerID
inner join Sales C ON b.CustomerID = c.CustomerID;
Due to this error I had to do 3 seperate insert into and that caused a bunch of nulls....
face palm is happening and could use some advice.
Image: enter image description here
Thanks,
VeryNew2SQL
You have used table ALIASES, so you have to use those aliases in you SELECT
A for Business, B for Customer and C for Sales.
Read about ALIASES here.
select A.BusinessID, B.CustomerID, A.BusName, B.Name, C.Territory, C.January2018, C.February2018, C.March2018, C.April2018, C.May2018, C.June2018
from Business A
inner join Customer B ON a.CustomerID = b.CustomerID
inner join Sales C ON b.CustomerID = c.CustomerID;
When you create a table alias in your FROM and JOIN clauses, you need to refer to the aliases in your SELECT statement and not the actual table names.
Alternatively, leave your SELECT statement as it is, and adjust your table names to remove the alias. You'll then need the join conditions to refer to your actual table names, rather than the alias. So for example;
select Business.BusinessID, Customer.CustomerID, Business.BusName, Customer.Name, Sales.Territory, Sales.January2018, Sales.February2018, Sales.March2018, Sales.April2018, Sales.May2018, Sales.June2018
from Business
inner join Customer ON Business.CustomerID = Customer.CustomerID
inner join Sales ON Customer.CustomerID = Sales.CustomerID;
Even just try running the SELECT statement above first to make sure you get the query correct before trying it in your insert.

SQLite join multiple values from two tables [duplicate]

Is there any difference (performance, best-practice, etc...) between putting a condition in the JOIN clause vs. the WHERE clause?
For example...
-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'
-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'
Which do you prefer (and perhaps why)?
The relational algebra allows interchangeability of the predicates in the WHERE clause and the INNER JOIN, so even INNER JOIN queries with WHERE clauses can have the predicates rearrranged by the optimizer so that they may already be excluded during the JOIN process.
I recommend you write the queries in the most readable way possible.
Sometimes this includes making the INNER JOIN relatively "incomplete" and putting some of the criteria in the WHERE simply to make the lists of filtering criteria more easily maintainable.
For example, instead of:
SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
ON ca.CustomerID = c.CustomerID
AND c.State = 'NY'
INNER JOIN Accounts a
ON ca.AccountID = a.AccountID
AND a.Status = 1
Write:
SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
AND a.Status = 1
But it depends, of course.
For inner joins I have not really noticed a difference (but as with all performance tuning, you need to check against your database under your conditions).
However where you put the condition makes a huge difference if you are using left or right joins. For instance consider these two queries:
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'
The first will give you only those records that have an order dated later than May 15, 2009 thus converting the left join to an inner join.
The second will give those records plus any customers with no orders. The results set is very different depending on where you put the condition. (Select * is for example purposes only, of course you should not use this in production code.)
The exception to this is when you want to see only the records in one table but not the other. Then you use the where clause for the condition not the join.
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null
Most RDBMS products will optimize both queries identically. In "SQL Performance Tuning" by Peter Gulutzan and Trudy Pelzer, they tested multiple brands of RDBMS and found no performance difference.
I prefer to keep join conditions separate from query restriction conditions.
If you're using OUTER JOIN sometimes it's necessary to put conditions in the join clause.
WHERE will filter after the JOIN has occurred.
Filter on the JOIN to prevent rows from being added during the JOIN process.
I prefer the JOIN to join full tables/Views and then use the WHERE To introduce the predicate of the resulting set.
It feels syntactically cleaner.
I typically see performance increases when filtering on the join. Especially if you can join on indexed columns for both tables. You should be able to cut down on logical reads with most queries doing this too, which is, in a high volume environment, a much better performance indicator than execution time.
I'm always mildly amused when someone shows their SQL benchmarking and they've executed both versions of a sproc 50,000 times at midnight on the dev server and compare the average times.
Agree with 2nd most vote answer that it will make big difference when using LEFT JOIN or RIGHT JOIN. Actually, the two statements below are equivalent. So you can see that AND clause is doing a filter before JOIN while the WHERE clause is doing a filter after JOIN.
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN (SELECT * FROM dbo.Orders WHERE OrderDate >'20090515') AS ORD
ON CUS.CustomerID = ORD.CustomerID
Joins are quicker in my opinion when you have a larger table. It really isn't that much of a difference though especially if you are dealing with a rather smaller table. When I first learned about joins, i was told that conditions in joins are just like where clause conditions and that i could use them interchangeably if the where clause was specific about which table to do the condition on.
Putting the condition in the join seems "semantically wrong" to me, as that's not what JOINs are "for". But that's very qualitative.
Additional problem: if you decide to switch from an inner join to, say, a right join, having the condition be inside the JOIN could lead to unexpected results.
It is better to add the condition in the Join. Performance is more important than readability. For large datasets, it matters.

Grouping data based on expression using CountDistinct aggregate function

I am newbie to Stack overflow and also SQL server reporting services. So please excuse me for the format of the question.
So here is the situation:
I am developing a SSRS report which needs to be grouped by an Count of Distinct product names as shown below.
I created a text box called ProdCount with an expression
COUNTDISTNCT(Fields!Product.value,"DataSet1")
which gives me the count 63 within the scope of DataSet1.
Now i need to group the data by taking product names where the above formula is >1 .
=IIF(ProdCount>1,Fields!Product.value,Nothing)
My Problem:
I tried to call the ProdCount from the calculated field since i
cant use the aggregate functions in Calculated Fields and use
the second expression by using
= ReportItems!ProdCount.value
which gives me an error FieldValue Denying ReportItems
I tried to combine the above two expressions by creating a calculated field by
IIF(CountDistinct(Fields!Product.Value,"DataSet1")>1,Fields!Product.Value,Nothing)
which gives me an error Calculated fields cannot have expressions
I tried to use Report Variables in the same way as above(1) which was not working either.
I also tried to use CROSS JOIN in the query
Select Count(Distinct(Product Name)
from Query1
Cross join
My Main Query which give me the data
which is taking more time to execute.
So Can anyone help me with solution where i can group the data by combining the above two expressions.
Please excuse me for the format. I was confused with framing question. I accept all your edits , so that i can learn in future.
Here is my code:
SELECT * FROM
--Query1 which counts the number of distinct products)
(SELECT DISTINCT COUNT(gproduct.ProductName) AS ProdCount
FROM Table1
LEFT JOIN Table4
ON Table1.column=Table1.column
LEFT JOIN Table2
ON Table3.Column = TTable1.Column
LEFT JOIN
(
SELECT Distinct Table6.Name AS ProductName,Table9.ColumnId
FROM Table6
INNER JOIN Table7
ON Table6.Column=Table7.Column
INNER JOIN Table8
ON Table7.Column=Table8.Column
INNER JOIN Table9
ON Table9.Column=Table8.Column
)gproduct
ON Table1.ColumnId=gproduct.ColumnId
GROUP BY gproduct.ColumnId,
)qProduct
CROSS JOIN
--My main Query which get data from different table including Product name
(SELECT
Upper(CASE WHEN (CASE WHEN Table4.Column =1 THEN 'Yes' ELSE 'NO' END)='YES'
THEN gab.ProductName
ELSE
Table2.productName
END) AS Product,
FROM Table1 AS ec
LEFT JOIN Table2 AS ep
ON --
LEFT JOIN Table3 AS ebrd
ON --
Left JOIN Table4 AS etpc
ON --
LEFT JOIN Table5 AS gst
ON --
LEFT JOIN
(
SELECT Distinct Table6.Name AS ProductName,Table9.ColumnId
FROM Table6
INNER JOIN Table7
ON Table6.Column=Table7.Column
INNER JOIN Table8
ON Table7.Column=Table8.Column
INNER JOIN Table9
ON Table9.Column=Table8.Column
) gab
ON Table1.ColumnId=gab.ColumnId
)QMain
Personally I would try to solve the problem in query itself instead of SSRS report. According the data you provided it would be something like:
SELECT
ProductName,
count(distinct Product)
from
YourTable
group by
ProductName
having count(distinct product) > 1
Later on creating SSRS report should be quite easy.

Is it possible to perform a join in Access on a second column if the first is blank?

I have this ugly source data with two columns, let's call them EmpID and SomeCode. Generally EmpID maps to the EmployeeListing table. But sometimes, people are entering the Employee IDs in the SomeCode field.
The person previously running this report in Excel 'solved' this problem by performing multiple vlookups with if statements, as well as running some manual checks to ensure results were accurate. As I'm moving these files to Access I am not sure how best to handle this scenario.
Ideally, I'm hoping to tell my queries to do a Left Join on SomeCode if EmpID is null, otherwise Left Join on EmpID
Unfortunately, there's no way for me to force validation or anything of the sort in the source data.
Here's the full SQL query I'm working on:
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
NZ([DDATransMaster]![DirectSellerNumber],[DDATransMaster]![PromotionCode]) AS EmpJoin,
EmployeeLookup.ID AS EmpLookup,
FROM FROM DDATransMaster
LEFT JOIN EmployeeLookup ON NZ([DDATransMaster]![DirectSellerNumber],[DDATransMaster]![PromotionCode]) = EmployeeLookup.[Employee #])
You can create a query like this:
SELECT
IIf(EmpID Is Null, SomeCode, EmpID) AS join_field,
field2,
etc
FROM YourTable
Or if the query will always be used within an Access session, Nz is more concise.
SELECT
Nz(EmpID, SomeCode) AS join_field,
field2,
etc
FROM YourTable
When you join that query to your other table, the Access query designer can represent the join between join_field and some matching field in the other table. If you were to attempt the IIf or Nz as part of the join's ON clause, the query designer can't display the join correctly in Design View --- it could still work, but may not be as convenient if you're new to Access SQL.
See whether this SQL gives you what you want.
SELECT
dda.Fulfillment,
dda.ConfirmationNumber,
dda.PromotionCode,
dda.DirectSellerNumber,
NZ(dda.DirectSellerNumber,dda.PromotionCode) AS EmpJoin,
el.ID AS EmpLookup
FROM
DDATransMaster AS dda
LEFT JOIN EmployeeLookup AS el
ON NZ(dda.DirectSellerNumber,dda.PromotionCode) = el.[Employee #])
But I would use the Nz part in a subquery.
SELECT
sub.Fulfillment,
sub.ConfirmationNumber,
sub.PromotionCode,
sub.DirectSellerNumber,
sub.EmpJoin,
el.ID AS EmpLookup
FROM
(
SELECT
Fulfillment,
ConfirmationNumber,
PromotionCode,
DirectSellerNumber,
NZ(DirectSellerNumber,PromotionCode) AS EmpJoin
FROM DDATransMaster
) AS sub
LEFT JOIN EmployeeLookup AS el
ON sub.EmpJoin = el.[Employee #])
What about:
LEFT JOIN EmployeeListing ON NZ(EmpID, SomeCode)
as your join, nz() uses the second parameter if the first is null, I'm not 100% sure this sort of join works in access. Worth 20 seconds to try though.
Hope it works.
You Could use a Union:
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
EmployeeLookup.ID AS EmpLookup
FROM DDATransMaster
LEFT JOIN EmployeeLookup ON
DDATransMaster.DirectSellerNumber = EmployeeLookup.[Employee #]
where DDATransMaster.DirectSellerNumber IS NOT NULL
Union
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
EmployeeLookup.ID AS EmpLookup
FROM DDATransMaster
LEFT JOIN EmployeeLookup ON
DDATransMaster.PromotionCode = EmployeeLookup.[Employee #]
where DDATransMaster.DirectSellerNumber IS NULL;

Multiple Joins in TSQL

I am trying to JOIN multiple tables to the same value in a table. So I have the table ActivityPartyBase and it has a column PartyId. I want to join COntactId in ContactBase table to PartyId and AccountId in AccountBase table to PartyId. This is the code I am using and it doesn't return anything. If I only join one it works. Any ideas?
SELECT DISTINCT Appointment.ScheduledStart, ActivityPartyBase.ActivityId
, Appointment.ActivityId AS Expr1, ActivityPartyBase.ScheduledStart AS Expr2
, Appointment.Subject, ActivityPartyBase.PartyId, ContactBase.ContactId
, ContactBase.FullName
FROM Appointment
INNER JOIN ActivityPartyBase
ON Appointment.ActivityId = ActivityPartyBase.ActivityId
INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId
LEFT OUTER JOIN ContactBase ON ActivityPartyBase.PartyId = ContactBase.ContactId
ORDER BY Appointment.ScheduledStart DESC
Your inner joins are filtering out results because there is no corresponding record on the joined table. I've always found the easiest way to debug is to "Select *" and use all LEFT JOINs. This will show you everything in your tables that relates to your main table; you should be able to look at your data and figure out what table is missing a record easily at that point.
To confirm that this is just a naming convention mismatch,
INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId
Are PartyID and AccountId the PK/FK?
Given this...
FROM Appointment
INNER JOIN ActivityPartyBase ON Appointment.ActivityId = ActivityPartyBase.ActivityId
INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId
LEFT OUTER JOIN ContactBase ON ActivityPartyBase.PartyId = ContactBase.ContactId
... you state this works (?) ...
FROM Appointment
INNER JOIN ActivityPartyBase ON Appointment.ActivityId = ActivityPartyBase.ActivityId
/* INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId */
/* LEFT OUTER JOIN ContactBase ON ActivityPartyBase.PartyId = ContactBase.ContactId */
Since the LEFT OUTER JOIN won't explicitly cause no results, that won't be your problem. Since the INNER JOIN will cause what you're seeing, we can only deduce that the join condition is incorrect.
In other words, ActivityPartyBase.PartyId is not equal to AccountBase.AccountID.
Are you sure there is data in all three tables in the inner join?
I'm guessing one of your INNER JOINs isn't picking up any data. Start with all 3 joins, then take out one of the joins at a time see which one breaks it. Then look at your join conditions and see which column isn't returning a record.
SOunds to me as if the tables are mutually exclusive. If it is ione table it is not inthe other (poor design). Try left joins to both tables.

Resources