One to many table joined to summary table - sql-server

I need to join following two tables:
Transactions (multiple rows per person)
LedgerSummary (Summary table) - one row per person
How do I join these two tables, but not get LedgerSummary data attached to each row of Transactions? I only want LedgerSummary data attached to first row of transaction per person (ID).
Both of these tables have PersonID column I can join on. However, LedgerSummary has an Amount field. The SUM(Amount) would be wrong if I do a regular left or right join because how these two tables are related. That is the reason I want Amount to only appear once for each person instead of every single row.

;With cteTransactions As
(
Select *, Row_Number() Over (Partition By IdThatLinksToTransAndLedger, Order By
ColumnToGivePriorityOnSelectingOneTransaction) SortOrder
From Transactions
)
Select *
From LedgerSummary L
Join (Select * From cteTransactions Where SortOrder = 1) T
On L.IdThatLinksToTransAndLedger = T.IdThatLinksToTransAndLedger
IdThatLinksToTransAndLedger - You need a key for Person
ColumnToGivePriorityOnSelectingOneTransaction - Priority column, usually a date descending to give most recent.

Related

How to get only last row after inner join?

I need to return unique funeral_homes who contains not completed leads and sort these by last lead timestamp.
This is my sql query:
select distinct h.funeral_home_name, h.funeral_home_guid, h.address1, h.city, h.state, p.discount_available, t.date_created
from tblFuneralHomes h inner join tblFuneralTransactions t on h.funeral_home_guid = t.funeral_home_guid
inner join vwFuneralHomePricing p on h.funeral_home_guid = p.funeral_home_guid where completed=0 order by 'funeral_home_name' asc;
This is the result, but I need only unique homes with last added lead
What I should change here?
The problem here appears that you are joining into tables with 1 to many relationships with table tblFuneralHomes, yet you expect only one row per funeral home.
Instead of using distinct, I would suggest that instead you group by the required output funeral home columns, and then apply some kind of aggregate on the columns needed from the joined tables in order to return just a single computed value from all possible joined values.
For instance, below we find the first transaction date (min) associated with each funeral home:
select h.funeral_home_name, h.funeral_home_guid, h.address1, h.city, h.state,
p.discount_available, min(t.date_created)
from tblFuneralHomes h
inner join tblFuneralTransactions t on h.funeral_home_guid = t.funeral_home_guid
inner join vwFuneralHomePricing p on h.funeral_home_guid = p.funeral_home_guid
where completed=0
group by h.funeral_home_name, h.funeral_home_guid, h.address1, h.city, h.state,
p.discount_available
order by h.funeral_home_name asc
Note that depending on the cardinality of the association between tblFuneralHomes and vwFuneralHomePricing, you may also need to remove p.discount_available from the grouping and also introduce it with an aggregate function, similar to what I've done with t.date_created

SQL query where person has as request for every product

I have a shortcut query where I just counted the total number of products and used count to display that the person has requested that many products. (Which is 8 products)
I want to know if there's an easier way where I wouldn't need to count the the products myself and have the query do it. Basically, replace the 8 with the total amount of products that the database has.
SELECT DISTINCT
Tb_Consumer.Name
FROM
Tb_Consumer, Tb_Product, Tb_Requests
WHERE
Tb_Consumer.Con_ID = Tb_Requests.Con_ID
AND Tb_Requests.Prod_ID = Tb_Product.Prod_ID
GROUP BY
Tb_Consumer.Name
HAVING
COUNT(Tb_Product.Name) = 8
Use a subquery to find the number of products in the Tb_Product table:
SELECT
tbc.Name
FROM Tb_Consumer tbc
INNER JOIN Tb_Request tbr
ON tbc.Con_ID = tbr.Con_ID
INNER JOIN Tb_Product tbp
ON tbr.Prod_ID = tbp.Prod_ID
GROUP BY
tbc.Name
HAVING
COUNT(tbp.Name) = (SELECT COUNT(*) FROM Tb_Product); -- count products here
This assumes that every record in Tb_Product corresponds to a single unique product. If there could be duplication for some reason, then you can count distinct products, e.g.
(SELECT COUNT(DISTINCT Name) FROM Tb_Product)
Other changes I made include removing DISTINCT from the select clause, since the GROUP BY should already make each name distinct. I also refactored your query to remove the commas in the FROM clause. Instead, I use explicit joins between the three tables.

MSSQL Group By failing, but no dup Column names

I know this question has been asked time and time again, but I have no two column names that are the same, yet I am getting:
Msg 8120, Level 16, State 1, Line 13 Column 'dbo.PRODUCT.ProductName'
is invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.
My ProductId column is unique to my dbo.Product Table, and I am not sure why it is getting confused with another value. In this image you can see the dup ProductIds
WITH products AS
(
SELECT
*,
ROW_NUMBER() OVER(ORDER BY p.[ProductName]) AS 'RowNumber'
FROM dbo.PRODUCT p
JOIN dbo.Category c ON p.ProductCategoryCode = c.CategoryCode
JOIN dbo.Supplier s ON p.ProductSupplierCode = s.SupplierCode
LEFT JOIN dbo.ProductTag pt ON pt.ProductUPC = p.UPC
LEFT JOIN dbo.Tag t ON pt.ProductTagTagCode = t.TagCode
GROUP BY p.ProductId
)
SELECT *
FROM products
WHERE RowNumber BETWEEN 0 AND 2;
Your error is because you are selecting ALL of the fields in ALL of the tables, but you are only grouping by one value. If a value is returned by the query, then it must either be GROUPED or aggregated (Min, Max, SUM, AVG, etcetera).
If you simply add the Product Name to your grouping:
GROUP BY p.ProductId, p.ProductName
You will still have the same problem with (for example) p.ProductCategoryCode, p.ProductSupplierCode, c.CategoryCode, etc, etc.
In this case, where you are looking for unique rows, do not use GROUP BY - use DISTINCT (which works on all fields returned automatically) instead. Note that #bjones is still correct as to why you are getting duplicates - one of the tables you are joining in can have multiple rows for each product (e.g. many times a product will come from more than one supplier.)
To solve this, you need to:
Determine what data you need to return, and only select those columns
Determine if you need to summarize any data (i.e. Total Sold or On Hand), then:
Use GROUP BY if you do need to summarize any values, or
Use DISTINCT if you do not need to summarize any values

Select value from different tables based on the column value in SQL Server

I have a main table A with the following fields:
Then I have three separate tables, each for Buildings, Classrooms and Offices. All these tables have two columns; ID and Name.
I want to query the table A to get the following result:
How can I do this?
Your data isn't really normalized. Having three separate tables all serving the same lookup is causing you some headache... so I unioned the 3 tables together and created a 'src' column so you could join table A's type and Id back to table B's ID and src. You'd have been better off having one table and non-repeating IDs and a type ID to specify if it's a building classroom or office.
Select *
from A
LEFT JOIN (SELECT 'Building' as src, ID, Name FROM Buildings UNION ALL
SELECT 'Classroom' as src, ID, Name FROM Classrooms UNION ALL
SELECT 'Office' as src, ID, Name FROM Offices) B
on A.Location_Type = B.Src
and A.LocationID = B.ID
I used a left join here in case not all records in A have an associated record in B. However, an inner join should work as well.
Should be doable with the use of a join.
Something along those lines should work:
SELECT tabelA.ID, tabelA.Subject, tabelA.Date, tabelA.locationType, tabelB.location
FROM tabelA INNER JOIN tabelB on tabelA.locationID = tabelB.locationID

How do I get the count of rows from two different tables in one result?

I have two tables from which I need to extract the NUMBER of rows belonging to the same ID.
Orders Table
Positions Table
I'm trying to build a query that will get me the amount of matching rows from the two tables, based on a common ID. I'm not looking for a result set that will return all matching rows, I only need back one value with the amount of matching rows found.
I've tried this next query, but I know there are in fact 48 rows when it returns 50.
select Isnull(CntPos,0)+IsNull(CntOrd,0)
from (select CID
,Count(*) CntPos
from [Serv].[Trade].[Position]
Group By CID
) Pos
Full join (select CID
,Count(*) CntOrd
from [Serv].[Stocks].[Orders]
Group By CID
) Ord
on Ord.[CID] = Pos.CID
WHERE Ord.CID=19556

Resources