SQL Query: customer name including activity count - sql-server

There's probably a very simple solution to this that I'm not seeing right now.
I need a script for an SQL report. I can get all customer names in a simple SELECT:
SELECT
t5.[Name] AS CustomerName
FROM
[T5] t5
WHERE
t5.Type IN (1, 2)
ORDER BY
t5.[Name]
This gives me an ordered list for the dropdown menu, to select the customer name. The result set looks like this:
CustomerName
------------
Customer 1 Name
Customer 2 Name
Customer 3 Name
...
But I don't just need the name, I need the number of related activities to that customer name inside the name string as well. For example, with 38 activities for that customer it should look like : "(38) Customer Name here"
The statement giving me the correct count for one particular customer (in this example, "Customer 5 Name") looks something like this, it needs a couple of joins to get there:
SELECT
COUNT(*)
FROM
[T1] t1
INNER JOIN
[T2] t2 ON t2.[ID] = t1.[Activity]
INNER JOIN
[T3] t3 ON t3.[ID] = t2.[Username]
INNER JOIN
[T4] t4 ON t4.[ID] = t3.[ID]
INNER JOIN
[T5] t5 ON t5.[ID] = t4.[X]
WHERE
t5.[Name] = 'Customer 5 Name'
Now obviously I need to combine these somehow, to get the following result set:
CustomerName
-------------------
(a) Customer 1 Name
(b) Customer 2 Name
(c) Customer 3 Name
(d) Customer 4 Name
(e) Customer 5 Name
(f) Customer 6 Name
...
(a-f being the respective activity count for that customer)
Thanks for help!

WITH pre AS
(
SELECT t5.[Name] AS CustomerName, COUNT(*) AS ActivityCount
FROM [T1] t1
INNER JOIN [T2] t2 ON t2.[ID] = t1.[Activity]
INNER JOIN [T3] t3 ON t3.[ID] = t2.[Username]
INNER JOIN [T4] t4 ON t4.[ID] = t3.[ID]
INNER JOIN [T5] t5 ON t5.[ID] = t4.[X]
WHERE t5.Type IN (1, 2) AND t5.[Name] = 'Customer 5 Name'
GROUP BY t5.Name
)
SELECT '(' + ActivityCount + ') ' + CustomerName
FROM pre

You should use group by
SELECT
t5.[Name], COUNT(*)
FROM
[T1] t1
INNER JOIN
[T2] t2 ON t2.[ID] = t1.[Activity]
INNER JOIN
[T3] t3 ON t3.[ID] = t2.[Username]
INNER JOIN
[T4] t4 ON t4.[ID] = t3.[ID]
INNER JOIN
[T5] t5 ON t5.[ID] = t4.[X]
group by t5.[Name]

I Think this will give you the number with the customer name as per your requirement.
SELECT
'(' + CAST(COUNT(*) AS nvarchar(4) ) + ') ' + t5.[Name] as [CustomerName]
FROM
[T1] t1
INNER JOIN
[T2] t2 ON t2.[ID] = t1.[Activity]
INNER JOIN
[T3] t3 ON t3.[ID] = t2.[Username]
INNER JOIN
[T4] t4 ON t4.[ID] = t3.[ID]
INNER JOIN
[T5] t5 ON t5.[ID] = t4.[X]
group by t5.[Name]

Related

SQL Server 2005 Select Data From Table1 and Table2 but if Table2 column1 value is null Select Data From Table3

My Query IS
SELECT TblPharmacyBillingDetails.UPBNo, TblMasterBillingData.IPDNo, InPatRegistration.PatTitle+PatientName, TblPharmacyBillingDetails.InvoiceNo, TblPharmacyBillingDetails.InvoiceDateTime, TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
but if TblMasterBillingData.IPDNo value is NULL select Data From TblMasterBillingData.OPDNo and
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.IPDNo
Method #1: Using UNION
SELECT * FROm
(
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.IPDNo,
InPatRegistration.PatTitle+PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
WHERE TblMasterBillingData.IPDNo IS NOT NULL
UNION ALL
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.OPDNo,
OutPatRegistration .PatTitle + PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.OPDNo
WHERE TblMasterBillingData.OPDNo IS NOT NULL
)Tmp
ORDER BY TblPharmacyBillingDetails.UPBNo
Method #2 Using ISNULL and LEFT JOIN
SELECT TblPharmacyBillingDetails.UPBNo,
ISNULL(TblMasterBillingData.IPDNo,TblMasterBillingData.OPDNo),
ISNULL(IP.PatTitle + IP.PatientName, OP.PatTitle + OP.PatientName),
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
LEFT JOIN InPatRegistration IP ON TblMasterBillingData.IPDNo = IP.IPDNo
LEFT JOIN outPatRegistration OP ON TblMasterBillingData.OPDNo = OP.OPDNo
ORDER BY TblPharmacyBillingDetails.UPBNo
You can write either case statement or ISNULL() function as shown below in the demo query.
SELECT
Orders.OrderID,
Case when Customers1.CustomerName is null then Customers2.CustomerName else Customers1.CustomerName
end as CustomerName, --way 1
ISNULL(Customers1.CustomerName, Customers2.CustomerName) as Customer, --way 2
Orders.OrderDate
FROM Orders
INNER JOIN Customers1 ON Orders.CustomerID = Customers1.CustomerID
INNER JOIN Customers2 ON Orders.CustomerID = Customers2.CustomerID
-- where your condition here
-- order by your column name
You can also check whether data is available or not in the table and join the table accordingly using if exists as shown below.
if exists(select 1 from tablename where columnname = <your values>)

how to Join five Tables with one another dependency in SQL

I want to join five tables in SQL server. The sequence as given below. Logic should be
Table1 >>>>Key : ID >>>> Table_A & Table_B (If Table1.Status = ABC then Table_A else Table_B ) >>> Key : NUMBER >>> Table2 >>> Key : Number + Item_No >>> Table3
Please help if below code could work.
SELECT * FROM
TABLE1
LEFT JOIN (CASE WHEN status = 'ABC' THEN Table_A ELSE Table_B END ) X ON (Table1.ID = X.ID)
LEFT JOIN Table2 ON (X.NUMBER = Table2.NUMBER)
LEFT JOIN Table3 ON (Table3.CONCAT(NUMBER + Item_No) = Table2.CONCAT(NUMBER + Item_No))
SELECT Q.*, T2.ItemNo, T2.Product, T3.Connection
FROM (
SELECT T1.ID, CASE WHEN T1.Status = 'ABC'
THEN TA.Number
ELSE TB.Number
END as Number
FROM Table1 T1
LEFT JOIN TableA TA
ON T1.ID = TA.ID
LEFT JOIN TableB TB
ON T1.ID = TB.ID
) as Q
JOIN Table2 T2
ON Q.Number = T2.Number
JOIN Table3 T3
ON T2.ItemNo = T3.ItemNo

Is it possible to Replace CTE and SELECT with just single sql query (dependent results)

I have the following query. Given productid as input (2,4,5) i want to get keyid associate with that list. Then i want to get all products associated with that keyids.
For example:
suppose i am passing productid as 2,4,5 as input to my sproc, i will get keyids as 22,34,35,38 (CTE result). This keys are mapped to the input productlist. Based on this keys (CTE result) i want all the products associated to this keys. Say the keyid = 22 will now have product names with product id as 2,4,5,89 & keyid = 34 will now have products associated to 2,4,5,23,45 etc.
I came up with the following solution for the above problem. I am just hoping whether we could somehow improve this solution or do this job in single query as two tables are getting repeated.
WITH GetKey_CTE
AS
(
SELECT k.id, some other select statements
FROM KeyDim k
INNER JOIN KeyData kd on kd.id = k.id
INNER JOIN KeyProductMapping kpm on kpm.id = k.id and kpm.mkey = k.mkey
INNER JOIN Products p on p.productid = kpm.productid
and p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions
)
SELECT cte.id as keyid, pn.productname, some other columns
FROM GetKey_CTE cte
INNER JOIN KeyProductMapping kpm on cte.id = kpm.id
INNER JOIN Products pn on pn.productid = kpm.productid
ORDER BY cte.id
Dataset Example for products and productkeymapping tables :
For Products table:
productid name
1 car
2 bike
3 plane
4 bus
5 train
45 cycle
ProductKeyMapping table
productid keyid
1 23
2 987
45 23
1 56
say input productid is 1, then final result should be:
keyid productid name
23 1 car
23 45 cycle
56 1 car
just looking at the data and that simple example
select pm2.*, product.name
from productmapping pm1
join productmapping pm2
on pm2.keyid = pm1.keyid
and pm1.productid in (1)
join product
on product.id = pm2.productid
declare #product table(id int, name varchar(20));
declare #map table(productid int, keyid int);
insert into #product values
(1, 'car'),
(2, 'bike'),
(3, 'plane'),
(4, 'bus'),
(5, 'train'),
(45, 'cycle');
insert into #map values
(1, '23'),
(2, '987'),
(45, '23'),
(1, '56');
select pm2.*, p.name
from #map pm1
join #map pm2
on pm2.keyid = pm1.keyid
and pm1.productid in (1)
join #product p
on p.id = pm2.productid
order by pm2.keyid;
you can also done by using sub query
SELECT * FROM KeyProductMapping km
INNER JOIN
(
SELECT k.id, some other select statements
FROM KeyDim k
INNER JOIN KeyData kd ON kd.id = k.id
INNER JOIN KeyProductMapping kpm ON kpm.id = k.id AND kpm.mkey = k.mkey
INNER JOIN Products p ON p.productid = kpm.productid
AND p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions) AS p ON p.id = km.id
INNER JOIN Products pn ON p.productid = km.productid
ORDER BY cte.id
SELECT cte.id as keyid, pn.productname, some other columns
FROM ( SELECT k.id, some other select statements
FROM KeyDim k
JOIN KeyData kd
on kd.id = k.id
JOIN KeyProductMapping kpm
on kpm.id = k.id
and kpm.mkey = k.mkey
JOIN Products p
on p.productid = kpm.productid
and p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions
) CTE
JOIN KeyProductMapping kpm
on cte.id = kpm.id
JOIN Products pn
on pn.productid = kpm.productid
ORDER BY cte.id
Above you you query with the CTE in line (a subquery)
A lot of stuff does not make sense to me
JOIN KeyProductMapping kpm
on kpm.id = k.id
and kpm.mkey = k.mkey
JOIN Products p
on p.productid = kpm.productid
and p.productid IN (2,4,5)
is the same as
JOIN KeyProductMapping kpm
on kpm.id = k.id
and kpm.mkey = k.mkey
and p.productid IN (2,4,5)
unless product does not have those values
why
SELECT k.id, some other select statements
FROM KeyDim k
JOIN KeyData kd
on kd.id = k.id
same as
SELECT kd.id -- move this to main select, some other select statements
FROM KeyData kd
why?
LEFT JOIN some more joins
move that to main statement
You can replace the CTE with an inline view like below but note sure why you are duplicating the JOINS again. Can you post some sample data along with your desired result to look further.
SELECT cte.id AS keyid, pn.productname, some other columns
FROM (
SELECT k.id, some other select statements
FROM KeyDim k
INNER JOIN KeyData kd ON kd.id = k.id
INNER JOIN KeyProductMapping kpm ON kpm.id = k.id AND kpm.mkey = k.mkey
INNER JOIN Products p ON p.productid = kpm.productid
AND p.productid IN (2,4,5)
LEFT JOIN some more joins
WHERE clause conditions ) cte
INNER JOIN KeyProductMapping kpm ON cte.id = kpm.id
INNER JOIN Products pn ON cte.productid = kpm.productid
ORDER BY cte.id

The multi part identifier could not be bound

I am getting this error while running following query
SELECT
T2.[AcctCode],
T2.[AcctName],
T5.[Name],
SUM(T0.[Debit]) AS Actual,
SUM(T3.[DebLTotal]) AS Budget
FROM [dbo].[JDT1] T0
INNER JOIN [dbo].[OJDT] T1
ON T0.[TransId] = T1.[TransId]
INNER JOIN [dbo].[OACT] T2
ON T0.[Account] = T2.[AcctCode],
[dbo].[OBGT] T#
INNER JOIN [dbo].[BGT1] T4
ON T3.[AbsId] = T4.[BudgId]
INNER JOIN OBGS T5
ON T3.[Instance] = T5.[AbsId]
WHERE T2.[AcctName] LIKE '%Travel%'
AND T5.[Name] LIKE 'Main Budget 2015'
GROUP BY T2.[AcctCode], T2.[AcctName], T5.[Name]

Get Max(id) from one to many table

I know this question was asked many times but I was tring and trying without success
I have one to many relationship between two tables and some more inner-joins to get more data.
Here is my query:
SELECT
ShopOffer.OfferID,
ShopOffer.OfferMessage,
Shop.ID,
Shop.Name,
Shop.Phone,
[User].Name,
[User].UserID,
ShopOfferStatus.Name AS StatusName,
BlockedShopInUser.IsBlocked
FROM
ShopOffer
INNER JOIN ShopOfferStatus ON ShopOffer.ShopOfferStatusID = ShopOfferStatus.ShopOfferStatusID
INNER JOIN Shop ON ShopOffer.ShopID = Shop.ShopID
INNER JOIN UserRequest ON ShopOffer.UserRequestID = UserRequest.UserRequestID
INNER JOIN [User] ON UserRequest.UserID = [User].UserID
INNER JOIN BlockedShopInUser ON Shop.ShopID = BlockedShopInUser.ShopID AND [User].UserID = BlockedShopInUser.UserID
Each shop can create many offers. In that query I would like to get only the last offer for each shop.
Thanks.
Here is a way:
;WITH LastShopOffer AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY ShopID ORDER BY OfferID DESC)
FROM ShopOffer
)
SELECT
SO.OfferID,
SO.OfferMessage,
S.ID,
S.Name,
S.Phone,
U.Name,
U.UserID,
SOS.Name AS StatusName,
B.IsBlocked
FROM ( SELECT *
FROM LastShopOffer
WHERE RN = 1) SO
INNER JOIN ShopOfferStatus SOS
ON SO.ShopOfferStatusID = SOS.ShopOfferStatusID
INNER JOIN Shop S
ON SO.ShopID = S.ShopID
INNER JOIN UserRequest UR
ON SO.UserRequestID = UR.UserRequestID
INNER JOIN [User] U
ON UR.UserID = U.UserID
INNER JOIN BlockedShopInUser B
ON S.ShopID = B.ShopID
AND U.UserID = B.UserID;
I think you have to start with Shop and then perform a CROSS APPLY on the TOP 1 record from ShopOffer:
SELECT
ShopOffer.OfferID,
ShopOffer.OfferMessage,
Shop.ID,
Shop.Name,
Shop.Phone,
[User].Name,
[User].UserID,
ShopOfferStatus.Name AS StatusName,
BlockedShopInUser.IsBlocked
FROM Shop
CROSS APPLY (
SELECT TOP 1 OfferID, OfferMessage, ShopOfferStatusID, UserRequestID
FROM ShopOffer AS s
WHERE s.ShopID = Shop.ShopID
ORDER BY s.OfferID DESC
) ShopOffer
INNER JOIN ShopOfferStatus ON ShopOffer.ShopOfferStatusID = ShopOfferStatus.ShopOfferStatusID
INNER JOIN UserRequest ON ShopOffer.UserRequestID = UserRequest.UserRequestID
INNER JOIN [User] ON UserRequest.UserID = [User].UserID
INNER JOIN BlockedShopInUser ON Shop.ShopID = BlockedShopInUser.ShopID AND [User].UserID = BlockedShopInUser.UserID

Resources