Left Join gives me a lot of duplicate value - google-bigquery

I have two tables.there are 3 common columns. When I use left join it gives me a lot duplicate values. How should I avoid the duplicate.

You need to use left join as below:
For Example:
SELECT
cu.Id
,cu.CustomerName,
_ord.Total
FROM Customers cu
LEFT JOIN
(
SELECT
customerId
,sum(amount) Total
FROM Orders
GROUP BY customerId
) _ord on _ord.customerId=cu.id

Related

Sql join select all values that not availible joined table

is it posssible to select all rows from one table and some rows from other table using join,
here is the what i'm trying to do.
Select CT.COA_TypeId,CT.Code,CT.Types,SUM(GL.Amount) As Amount
from COA_Type CT
join ChartOfAccount CA on CT.COA_TypeId=CA.COA_Id
Join COA_Client CC on CA.COA_Id = CC.COA_Id
JOIN GeneralLedgerLine GL on CC.AccountId=GL.AccountId
Group BY CT.Code,CT.Types,CT.COA_TypeId
i want to select all CT.Types with amount, type rows that do not have Amount i want amount as null
Select CT.COA_TypeId,CT.Code,CT.Types,SUM(GL.Amount) As Amount
from COA_Type CT
INNER join ChartOfAccount CA on CT.COA_TypeId=CA.COA_Id
INNER Join COA_Client CC on CA.COA_Id = CC.COA_Id
LEFT JOIN GeneralLedgerLine GL on CC.AccountId=GL.AccountId
Group BY CT.Code,CT.Types,CT.COA_TypeId
By changing GeneralLedgerLine from an INNER JOIN to a LEFT JOIN, you will still get COA_Type records even though there isn't a matching GeneralLedgerLine.
NOTE: You might have to make the other joins into LEFT JOIN as well.

SQL Server Joins Beginner simple join

I have the following two tables:
dbo.orders:
customerid
orderid
dbo.customerprofiletbl:
customerid
customername
I am attempting to put together a join but I am failing:
select
dbo.orders.customerid AS orde,
dbo.customerprofiletbl.customerid AS cust
from
dbo.customerprofiletbl
left join
orde on cust
Help?
What you need to do is:
select
orde.customerid AS orde,
cust.customerid AS cust
from dbo.customerprofiletbl cust
LEFT JOIN dbo.orders orde on cust.customerid = orde.customerid
You are getting the values from the columns using the table alias's you created (orde and cust) and calling the new columns the same name, but that doesn't matter - you could have done as OrderCustomerId for example..
When joining, you join one table to another, and you can use the table alias's to make things easier. When you join 2 tables, you have to tell it when columns to use to create the join on - using the alias's helps here.
You have some of your query a little backwards. You should be putting the table name of the joining table in the join statement (you can still alias it there), and then in the list if select columns you can also use just the alias:
SELECT
orde.customerid,
cust.customerid
FROM
dbo.customerprofiletbl cust
LEFT JOIN
dbo.orders orde
ON
cust.customerid = orde.customerid
select dbo.orders.customerid AS orde,
dbo.customerprofiletbl.customerid AS cust
from dbo.customerprofiletbl
LEFT JOIN orde on dbo.customerprofiletbl.customerid = orde.customerid
Although it seems you are in wrong direction. But your query is like
Select o.customerid as orde, cpt.customerid AS cust from dbo.orders o left join dbo.customerprofiletbl cpt on o.customerid=cpt.customerid
CustomerProfiletbl should be on left side as there is no way order can be done without customer
You must specify the columns where join is made
Just add the ON Clause
select
dbo.orders.orderid
dbo.customerprofiletbl.customerid
Dbo.customerprofiletbl.customername
from dbo.customerprofiletbl
LEFT JOIN dbo.orders ON dbo.customerprofiletbl.customerid = dbo.orders.customerid

Trying to understand NULL operator in Query

I'm looking to see a breakdown of the total dollar business that each vendor has done (indirectly via the distributor) with each customer, where I'm trying not to use the Inner Join Syntax. I basically don't understand the difference between the two outputs produced by the two queries shown below:
Query1
select customers.cust_id, vendors.vend_id, sum(OrderItems.item_price*OrderItems.quantity) as total_business from
(((Vendors left outer join products
on vendors.vend_id = products.prod_id)
left outer join OrderItems
on products.prod_id = OrderItems.prod_id)
left outer join Orders
on OrderItems.order_num = Orders.order_num)
left outer join Customers
on Orders.cust_id = Customers.cust_id
group by Customers.cust_id, vendors.vend_id
order by total_business
I get the following output:
Query2
select customers.cust_id, Vendors.vend_id, sum(quantity*item_price) as total_business from
(((Vendors left outer join Products
on Products.vend_id = Vendors.vend_id)
left outer join OrderItems --No inner joins allowed
on OrderItems.prod_id = Products.prod_id)
left outer join Orders
on Orders.order_num = OrderItems.order_num)
left outer join Customers
on Customers.cust_id = Orders.cust_id
where Customers.cust_id is not null -- THE ONLY DIFFERENCE BETWEEN QUERY1 AND QUERY2
group by Customers.cust_id, Vendors.vend_id
order by total_business
I don't understand how there are only NULL cust_id's associated with the 1st Output when in the 2nd Output we get some non-NULL cust_ids. Why doesn't the 1st Output include these non-NULL cust_id's
Thank You
Query One is joining Vendors and Products incorrectly:
on vendors.vend_id = products.prod_id -- Vend_ID = Prod_ID
Query Two is joining Vendors and Products correctly:
on Products.vend_id = Vendors.vend_id -- Vend_ID = Vend_ID
Once that is fixed, you'll get the same IDs in both queries. Then I suggest you read Dan's answer to understand why what you were trying to do in eliminating INNER JOIN from the query is cancelled out by adding a WHERE filter to a column from the last table in the chain.
When you left join to a table, then filter on that table in the where clause, the join effectively changes to an inner join. The workaround is to apply the filter as a joining condition.
In your second query, all you have to do is is change the word "where" to "and".

Combine Two Tables in Select (SQL Server 2008)

If I have two tables, like this for example:
Table 1 (products)
id
name
price
agentid
Table 2 (agent)
userid
name
email
How do I get a result set from products that include the agents name and email, meaning that products.agentid = agent.userid?
How do I join for example SELECT WHERE price < 100?
Edited to support price filter
You can use the INNER JOIN clause to join those tables. It is done this way:
select p.id, p.name as ProductName, a.userid, a.name as AgentName
from products p
inner join agents a on a.userid = p.agentid
where p.price < 100
Another way to do this is by a WHERE clause:
select p.id, p.name as ProductName, a.userid, a.name as AgentName
from products p, agents a
where a.userid = p.agentid and p.price < 100
Note in the second case you are making a natural product of all rows from both tables and then filtering the result. In the first case you are directly filtering the result while joining in the same step. The DBMS will understand your intentions (regardless of the way you choose to solve this) and handle it in the fastest way.
This is a very rudimentary INNER JOIN:
SELECT
products.name AS productname,
price,
agent.name AS agentname
email
FROM
products
INNER JOIN agent ON products.agentid = agent.userid
I recommend reviewing basic JOIN syntax and concepts. Here's a link to Microsoft's documentation, though what you have above is pretty universal as standard SQL.
Note that the INNER JOIN here assumes every product has an associated agentid that isn't NULL. If there are NULL agentid in products, use LEFT OUTER JOIN instead to return even the products with no agent.
select p.name productname, p.price, a.name as agent_name, a.email
from products p
inner join agent a on (a.userid = p.agentid)
This is my join for slightly larger tables in Prod.Hope it helps.
SELECT TOP 1000 p.[id]
,p.[attributeId]
,p.[name] as PropertyName
,p.[description]
,p.[active],
a.[appId],
a.[activityId],
a.[Name] as AttributeName
FROM [XYZ.Gamification.V2B13.Full].[dbo].[ADM_attributeProperty] p
Inner join [XYZ.Gamification.V2B13.Full].[dbo].[ADM_activityAttribute] a
on a.id=p.attributeId
where a.appId=23098;
select ProductName=p.[name]
, ProductPrice=p.price
, AgentName=a.[name]
, AgentEmail=a.email
from products p
inner join agent a on a.userid=p.agentid
If you don't want to use inner join (or don't have possibility to do it!) and would combine rows, you can use a cross join :
SELECT *
FROM table1
CROSS JOIN table2
or simply
SELECT *
FROM table1, table2

Using sum with a nested select

I'm using SQL Server. This statement lists my products per menu:
SELECT menuname, productname
FROM [web].[dbo].[tblMenus]
FULL OUTER JOIN [web].[dbo].[tblProductsRelMenus]
ON [tblMenus].Id = [tblProductsRelMenus].MenuId
FULL OUTER JOIN [web].[dbo].[tblProducts]
ON [tblProductsRelMenus].ProductId = [tblProducts].ProductId
LEFT JOIN [web].[dbo].[tblOrderDetails]
ON ([tblProducts].Id = [tblOrderDetails].ProductId)
GROUP BY [tblProducts].ProductName
Some products don't have menus and vice versa. I use the following to establish what has been sold of each product.
SELECT [tblProducts].ProductName, SUM([tblOrderDetails].Ammount) as amount
FROM [web].[dbo].[tblProducts]
LEFT JOIN [web].[dbo].[tblOrderDetails]
ON ([tblProducts].ProductId = [tblOrderDetails].ProductId)
GROUP BY [tblProducts].ProductName
What I want to do is complement the top table with an amount column. That is, I want a table with the same number of rows as in the first table above but with an amount value if it exists, otherwise null.
I can't figure out how to do this. Any suggestions?
If I am not missing anything, the second query could be simplified, then incorporated into the first query like this:
SELECT
m.menuname,
p.productname,
t.amount
FROM [web].[dbo].[tblMenus] m
FULL JOIN [web].[dbo].[tblProductsRelMenus] pm ON m.Id = pm.MenuId
FULL JOIN [web].[dbo].[tblProducts] p ON pm.ProductId = p.ProductId
LEFT JOIN (
SELECT ProductId, SUM(Amount) as amount
FROM [web].[dbo].[tblOrderDetails]
GROUP BY ProductId
) t ON p.ProducId = t.ProductId