sql server duplicated result while getting data from multiple tables - sql-server

Hi i have a small problem with SQL SERVER .
an building a Purchase and stokes system i want to retrieve data from 3 Tables:-
Tables Structure
Query:
SELECT Tbl_Products.Product_Name, Tbl_PurchaseDetails.BuyPrice, Tbl_PurchaseDetails.AllPieceBoxes, Tbl_PurchaseDetails.TotalPrice, Tbl_PurchaseHeader.purchaseOrder
FROM Tbl_Products
INNER JOIN Tbl_PurchaseHeader ON Tbl_Products.Product_ID = Tbl_PurchaseHeader.ProductId
INNER JOIN Tbl_PurchaseDetails ON Tbl_PurchaseHeader.purchaseOrder = Tbl_PurchaseDetails.PurchaseOrder
Query Result
Product_Name BuyPrice AllPieceBoxes TotalPrice purchaseOrder
-------------------- -------- ------------- ---------- -------------
Dell Alien-Ware 2500.000 5 12500.000 1
KINGSTON-Desktop 8GB 2500.000 5 12500.000 1
Dell Alien-Ware 95.00 10 950.000 1
KINGSTON-Desktop 8GB 95.00 10 950.000 1

Given the join below I think you have multiple rows for a given Product_ID in Tbl_PurchaseHeader which you then join with tbl_PurchaseDetails. For example if there are two rows in Tbl_PurchaseHeader with Product_ID of 1 then you will join with Tbl_PurchaseDetails twice so 1 Tbl_Products gives 2 Tbl_PurchaseHeader's which if there are multiple (say 3) rows in Tbl_PurchaseDetails then you'll get an additional 2 x 3 so 6 rows.
FROM Tbl_Products
INNER JOIN Tbl_PurchaseHeader ON Tbl_Products.Product_ID = Tbl_PurchaseHeader.ProductId
INNER JOIN Tbl_PurchaseDetails ON Tbl_PurchaseHeader.purchaseOrder = Tbl_PurchaseDetails.PurchaseOrder
Check out your data, do a singleton SELECT against each table and track the data through to see how many rows come back for a) Product_ID and then for PurchaseOrder.

Related

How do I join 2 tables in SQL Server

I have two tables as follows that the id values of the tblBranch table in the tblPost table are in the Cityid, catid, Desid columns
How can I join these two tables together to see the values of cityid, catid, Desid?
tblBranch tblPost
---------- -----------
id id
Name title
cityid
catid
Desid
When you are join tables, you are bringing/combine TWO TABLES data rows
and their columns into ONE BIG TABLE base on the MATCHING JOIN COLUMNS.
Here is example of inner join:
tblDepartment
--------------
id_Dept NameDept
1 Math
2 Physic
tblTeacher
----------
id_Teacher FullName id_Dept
1 Smith Adam 1
2 John Doe 1
3 Marry Doe 2
EXAMPLE 01: No rows filter
select TC.id_Teacher, TC.FullName, TC.id_Dept, TD.NameDept from tblTeacher TC inner join tblDepartment TD on TC.id_Dept = TD.id_Dept
Result ONE BIG TABLE OF JOINING TABLES
id_Teacher FullName id_Dept NameDept
1 Smith Adam 1 Math
2 John Doe 1 Math
3 Marry Doe 2 Physic
EXAMPLE 02: With rows filter
Result ONE BIG TABLE OF JOINING TABLES with SQL where clause to limit smaller set of data rows return
select TC.id_Teacher, TC.FullName, TC.id_Dept, TD.NameDept from tblTeacher TC inner join tblDepartment TD on TC.id_Dept = TD.id_Dept
where TC.id_Dept = 2
id_Teacher FullName id_Dept NameDept
3 Marry Doe 2 Physic
You can use the above example to see WHAT COLUMNS your table should join to return result with BIG TABLE
So if I understand you correctly, you want to take CityId, CatId and DesId from tblPost, and for each of them, you want to join to the tblBranch table and show the Name for that Id - correct?
In that case, you need a query like this:
SELECT
CityId,
CityName = brCity.Name,
CatId,
CatName = brCat.Name,
DesId,
DesName = brDes.Name
FROM
tblPost p
LEFT OUTER JOIN
tblBranch brCity ON p.CityId = brCity.Id
LEFT OUTER JOIN
tblBranch brCat ON p.CatId = brCat.Id
LEFT OUTER JOIN
tblBranch brDes ON p.DesId = brDes.Id
Basically, you need to have three joins - one for each of the Id in your tblPost table.
I chose to use LEFT OUTER JOIN to avoid eliminating a row completely, if one of the Id cannot be found/matched in the tblBranch table.

Perform Query Using Columns of Table as Arguments

I need to perform different queries with different arguments. These arguments are arranged in the table T2 below. Everyday these arguments change so the table T2 change and the result of the query I want to do will change. The query is simple but I dont know how to perform using the columns of T2 as arguments...
-----Table T2----
ID Country FilterExpression
----------- ------- ------ ----- -----
1 Argentina 'Filter01'
2 Brazil 'Filter02'
3 USA 'Filter03'
4 UK 'Filter04'
5 France 'Filter05'
6 Mexico 'Filter06'
...
100 Canada 'Filter100'
The query I need to perform:
SELECT Element,Value
FROM ArchTot
WHERE Country = [Column Country of T2]
AND FilterExpr = [Column FilterExpression of T2]
Once I have a Table of arguments of 100 rows, the result of my query must have the same 100 rows.
Somebody can help me to build this query?
Try to be more specific so I can understand what you need to do.. Why you need to retrieve 100 for 100? And when The table data changes what happens to The old data... You need to query new data or The data before it changes?
Everyday the table of arguments change so I have to perform the query to update the Result. Once I Have 100 arguments I'll have 100 results:
Result of query from Tables Archtot or Archtot2
Country FilterExpr Value
----------- ------- ------ ----- -----
Argentina 'Filter01' 100.82
Brazil 'Filter02' 102.87
USA 'Filter03' 82.7
UK 'Filter04' 106.8
France 'Filter05' 110.7
Mexico 'Filter06' 79.9
...
Canada 'Filter100' 102.04
I Tried the following, It works...
SELECT A.Element,A.Value
FROM ArchTot A, T2 B
WHERE A.Country = B.Country
AND A.FilterExpr = B.FilterExpression
The problem now is that I Cant perform a INNER JOIN Statement once I have inserted the Table T2 in the FROM clause, it gives timeout. For example:
SELECT * FROM
(
(SELECT A.Element As Element,A.Value As Value, A.Country As Country
FROM ArchTot A, T2 B
WHERE A.Country = B.Country
AND A.FilterExpr = B.FilterExpression)T1
INNER JOIN
(SELECT C.Element As Element,C.Value As Value, C.Country As Country
FROM ArchTot2 C, T2 D
WHERE C.Country = D.Country
AND C.FilterExpr = D.FilterExpression)T2
ON T1.Country=T2.Country
)
Is the query I Built OK? Any Ideas why I Cant Perform the INNER JOIN?

How to return a SQL Server view that can divide fees?

I know this is kind of odd but I was wondering if I can do it using PURELY SQL-T script language
So here is the question, imagine we have 2 tables
Table purchasing
purchase_id, payment_id, xxxx, xxxx
1 1
2 1
3 1
Table of payment
payment_id, processing fee, xxx, xxx
1 9
One payment record can be related to multiple purchase records. Kinda like a cart system that you can pay for all the stuff that's in your cart.
And I can now create a View in the SQLServer to return all the purchase record + fields in the payment table like this
The View
purchase_id, payment_id, processing_fee
1 1 9
2 1 9
3 1 9
But, as you can see, the processing fee really should be divided into 3 equal pieces, I want the view to show this
purchase_id, payment_id, processing_fee
1 1 3
2 1 3
3 1 3
Here comes the question, is it possible? And if that's possible, how?
Use OVER Clause, this was introduced in sqlserver 2005:
SELECT
pur.purchase_id,
pur.payment_id,
1.0 * pay.processing_fee /
count(*) over (partition by pur.payment_id) as calculated_processing_fee
FROM purchasing pur
JOIN payment pay ON pur.payment_id = pay.payment_id
It's possible, but I'm not sure it's wise, since processing_fee is a part of the payment table, and not of the purchasing table.
Here is one way of doing it:
;With cte as
(
SELECT payment_id, COUNT(purchase_id) As NumberOfPurchases
FROM purchasing
GROUP BY payment_id
)
SELECT purchase_id,
purchasing.payment_id,
processing_fee / NumberOfPurchases As processing_feePerPurchase
FROM purchasing
INNER JOIN cte ON(purchasing.payment_id = cte.payment_id)
INNER JOIN payment ON(p.payment_id = payment.payment_id)
Note: Code was written directly here, there might be some mistakes.
You can use COUNT(PU.payment_id)OVER(PARTITION BY PU.payment_id) to get the count of purchasing records for a payment record.
;WITH purchase(purchase_id,payment_id) as
(
SELECT 1,1
UNION ALL SELECT 2,1
UNION ALL SELECT 3,1
UNION ALL SELECT 3,2
), payment(payment_id,processingfee) as
(
SELECT 1,9
UNION ALL SELECT 2,10
)
SELECT PU.purchase_id,PU.payment_id,PA.payment_id,PA.processingfee / COUNT(PU.payment_id)OVER(PARTITION BY PU.payment_id)
FROM
purchase PU INNER JOIN payment PA ON PU.payment_id = PA.payment_id

Selecting data from one table on the basis of another tables data one by one - SQL Server 2008

I have 3 tables
Table 1 - CommonTable
Id Section
____________________
1 Two-Wheeler
2 Three-Wheeler
Table 2 - CategoryTbl
Id Category Section
___________________________________________________
1 Two Wheeler Two-Wheeler
2 Three Wheeler Three-Wheeler
3 Four Wheeler Four-Wheeler
4 Other Others
Table 3 - ContentTbl
Id CategoryId Item
___________________________________________________
1 1 Bike
2 1 Scooter
3 1 Cycle
4 2 Car
5 2 Jeep
6 4 Truck
And the desired output is
Vehicle/Two-Wheeler/Bike
Vehicle/Two-Wheeler/Scooter
Vehicle/Two-Wheeler/Cycle
Vehicle/Three-Wheeler/Car
Vehicle/Three-Wheeler/Jeep
I tried to write following query
Select 'Vehicle/'+(select section from CommontTbl)+'/'+select item from
contenttbl where CategoryId=(select section from CommontTbl)
I know this query is wrong because select section from commontbl will return
multiple values, so how can i fix this, using join or any thing please help me to find desired output
Try this,
Select 'Vehicle/' + b.Category + '/' + a.Item from ContentTbl as a
left join CategoryTbl as b on a.CategoryId=b.ID
And if you want to Records from CommonTbl as base then try following,
Select 'Vehicle/' + b.Category + '/' + a.Item from ContentTbl as a
left join CategoryTbl as b on a.CategoryId=b.ID
inner join CommonTable as c on c.Section = b.Section

Filtering data from two or more tables in SQL server 2008

I have a few tables:
"DCDetails" table which contains the Master data for a few diagnostics centers.
"CompanyDetails" table which contains the Master data for Companies
"Investigation" table which contains the Investigations(meaning set of medical tests to be conducted)
These are my master tables.
I also have a few mapping tables:
1. "CompanyDCMap" table which contains the MAPPING of Company to Diagnostic centers
2. "InvestigationDCMap" table which contains the MAPPING of Investigation to Diagnostic centers(Or DC for short)
I have to filter a set of DC based on two criteria which are:
the DC belongs in the "CompanyDCMap" and
Out of the DC filtered in (1), it also belongs in the "InvestigationDCMap" table.
How do I write the query for this so that I get the DC which are in both CompanyDCMap and InvestigationDCMap given I have the primary keys of "CompanyDetails" and "Investigation" tables.
I have almost given up, I am unable to think of a query which filters two sets at the same time.
Kindly help me.
UPDATE
Schema:
CompanyDetails table:
CompanyID(PRIMARY KEY), CompanyName(NVARCHAR(100))
1 Company1
2 Company2
3 Company3
Investigation Table:
InvestigationID(Primary key) , InvestigationName(NVARCHAR(100))
1 HIV+ Blood Test
2 TMT
3 Urine Test
DCDetails Table:
DCID(PRIMARY KEY), DCName(NVARCHAR(100))
1 DC1
2 DC2
3 DC3
CompanyDCMap table
CompanyDCMapID(Primary key), CompanyID(Foreign key), DCId(Foreign Key)
1 1 1
2 1 2
3 2 2
4 2 3
5 3 1
6 3 3
InvestigationDCMap table
InvestigationDCMapID(Primary Key), InvestigationID(Foreign Key), DCId(Foreign Key)
1 1 1
2 1 3
3 2 2
4 2 3
Expected Output of a query given CompanyID = 1 and InvestigationID = 2, SELECT DCId and DCName =
DCId(Int) DCName(NVARCHAR(100))
2 DC2
SELECT d.DCID, d.DCName
FROM dbo.DCDetails AS d
INNER JOIN dbo.CompanyDCMap AS c
ON d.DCID = c.DCId
INNER JOIN dbo.InvestigationDCMap AS i
ON i.DCId = d.DCID;
To get "distinct" values, you can use:
SELECT DISTINCT d.DCID, d.DCName
FROM dbo.DCDetails AS d
INNER JOIN dbo.CompanyDCMap AS c
ON d.DCID = c.DCId
INNER JOIN dbo.InvestigationDCMap AS i
ON i.DCId = d.DCID;
Or...
SELECT d.DCID, d.DCName
FROM dbo.DCDetails AS d
INNER JOIN dbo.CompanyDCMap AS c
ON d.DCID = c.DCId
INNER JOIN dbo.InvestigationDCMap AS i
ON i.DCId = d.DCID
GROUP BY d.DCID, d.DCName;
Better yet, since no relationships with the other tables are needed:
SELECT d.DCID, d.DCName
FROM dbo.DCDetails AS d
WHERE EXISTS (SELECT 1 FROM dbo.CompanyDCMap WHERE DCId = d.DCID)
AND EXISTS (SELECT 1 FROM dbo.InvestigationDCMap WHERE DCId = d.DCID);
This will be a much more efficient query, but if you need other columns from the other tables, you'll need to revert to the join version.

Resources