How to DISTINCT one column in stored procedure - sql-server-2008

I wrote one stored procedure.
My requirement is i have to show the data like if any No column has different Account_Names i have to show like Account_Name :Multipul(varchar))
Create PROCEDURE [dbo].[OpenVendorBIllsSP] (#FromDate Date,#ToDate Date)
AS
BEGIN
select
ROW_NUMBER() OVER(Order by vendor.VendorName ) AS ID,
PH.PurchasingHeaderID as No,
PH.TotalPriceCompanyCurrency as Balance,
acc.AccountName as [Account_Name],
PD.LineMemo as Memo,
from PurchasingHeader PH
LEFT OUTER JOIN TransactionType Trans ON PH.TransactionTypeID =Trans.TransactionTypeID
LEFT OUTER JOIN Vendor vendor on PH.VendorID=vendor.VendorID
LEFT OUTER JOIN PaymentTerm PT on PT.PaymentTermID = vendor.PaymentTermID
LEFT OUTER JOIN PurchasingDetail PD on PD.PurchasingHeaderID = PH.PurchasingHeaderID
LEFT OUTER JOIN Account Acc on Acc.AccountID= PD.FinancialAccountID
where PH.TransactionTypeID=7
Group by vendor.VendorName,
PH.PurchasingHeaderID,PH.TotalPriceCompanyCurrency,acc.AccountName
END
GO
with this result:
ID No Account_Name Balance Memo**
-------------------------------------------------------------
101 VB1000 Cash-Petty Cash 4000.00 Memo
102 VB1001 Accounts Receivable 5000.00 Memo
103 VB1003 Cash-PettyCash 6000.00 Memo
104 VB1003 Cash-PettyCash 6000.00 Memo
105 VB1004 UndepositedFunds 7000.00 Memo
I need this result :
ID No Account_Name Balance Memo
------------------------------------------------------
101 VB1000 Cash-PettyCash 4000.00 Memo1
102 VB1001 AccountsReceivable 5000.00 Memo2
103 VB1003 ---Multiple---- 6000.00 Memo3
104 VB1004 UndepositedFunds 7000.00 Memo4
Can any one tell me how can i write the sp to get aboue result.
Edited SP :
select
ROW_NUMBER() OVER(Order by vendor.VendorName ) AS ZID,
PH.PurchasingHeaderID as No,
PH.TotalPriceCompanyCurrency as Balance,
Case When count(PH.PurchasingHeaderID) > 1 Then 'Multipul' else acc.AccountName END
from PurchasingHeader PH
LEFT OUTER JOIN TransactionType Trans ON PH.TransactionTypeID =Trans.TransactionTypeID
LEFT OUTER JOIN Vendor vendor on PH.VendorID=vendor.VendorID
LEFT OUTER JOIN PaymentTerm PT on PT.PaymentTermID = vendor.PaymentTermID
LEFT OUTER JOIN PurchasingDetail PD on PD.PurchasingHeaderID = PH.PurchasingHeaderID
LEFT OUTER JOIN Account Acc on Acc.AccountID= PD.FinancialAccountID
where PH.TransactionTypeID=7
Group by vendor.VendorName,PH.PurchasingHeaderID ,
PH.PurchasingHeaderID,PH.TotalPriceCompanyCurrency,acc.AccountName

You could do a subsection that has everything, then GROUP BY acc.AccountName, PH.TotalPriceCompanyCurrency, etc and do a CASE WHERE COUNT(acc.AccountName) > 1

Related

Join three tables and subtract sum of column from a column data

I have three tables accounts, receivables and receiveds .
My basic table is receivables I want to get the names from the account table and then subtract the sum of received column in receiveds table form the receivable column in receivables table with same ref numbers. i want to ignore if the balance is zero.
accounts
id
name
22
John
23
Kahn
24
Falis
25
Haseni
26
Gent
receivables
id
receivable
Ref
22
70
A1
24
100
A2
26
60
A3
24
15
A4
receiveds
ref
id
received
A1
22
30
A2
24
60
A1
22
40
A3
26
20
A2
24
10
desired results
id
name
ref
receivable
received
balance
total_id_balance
24
Falis
A2
100
70
30
45
26
Gent
A3
60
20
40
40
24
Falis
A4
15
0
15
45
I have tried this code but it's not working for me
SELECT *
FROM receivables AS rvb
LEFT JOIN accounts AS acc
ON rvb.id = acc.id
LEFT JOIN (SELECT SUM(received) as sum_rvd FROM receiveds) AS rvd
ON acc.id = rvd.id where rvb.receivable>rvd.sum_rvd
INNER JOINs filter out NULL values and the HAVING clause removes zero-balance rows.
SELECT
accounts.* ,
ra.receivable,
rd.received,
ra.receivable - rd.received as balance
FROM accounts
INNER JOIN ( SELECT id, SUM(receivable) as receivable FROM receivables GROUP BY id ) ra
ON ra.id = accounts.id
INNER JOIN ( SELECT id, SUM(received) as received FROM receiveds GROUP BY id ) rd
ON rd.id = accounts.id
HAVING balance > 0
UPDATE
With a ref field we just need to add it as another grouping field for subselects, and change second INNER JOIN to LEFT JOIN (actually looks like it was a mistake from the start, coz we missed entries without receiveds that still had positive balance). Also changing received field to a COALESCE to get zeroes instead of NULL's (indicating non existing rows in a receiveds table).
Since you need an overall per-id total_id_balance field, the natural way to grab it - is using window functions. Note, they are supported only for MySQL 8.0+.
So the resulting query looks like this:
SELECT
accounts.* ,
ra.ref,
ra.receivable,
COALESCE(rd.received, 0) as received,
ra.receivable - COALESCE(rd.received, 0) as balance,
SUM( ra.receivable - COALESCE(rd.received, 0) ) OVER ( PARTITION BY id ) as total_id_balance
FROM accounts
INNER JOIN ( SELECT id, SUM(receivable) as receivable, ref FROM receivables GROUP BY id, ref ) ra
ON ra.id = accounts.id
LEFT JOIN ( SELECT id, SUM(received) as received, ref FROM receiveds GROUP BY id, ref ) rd
ON
rd.id = accounts.id
AND
ra.ref = rd.ref
HAVING balance > 0
ORDER BY ref
This work for me -
EDIT-
Add support for non-unique id in receivables
SELECT acc.id ,acc.name, res.receivable, res.received, (res.receivable - res.received) AS balance
FROM accounts AS acc JOIN
(SELECT recv.id, recv.receivable, rec.received
FROM (
SELECT id, SUM(receivable) AS receivable
FROM receivables
GROUP BY id) AS recv JOIN
(SELECT id, SUM(received) AS received
FROM receiveds
GROUP BY id) AS rec ON rec.id = recv.id
WHERE rec.received < recv.receivable) AS res ON res.id = acc.id;
Assuming it is possible to have an id in receivables without a corresponding id in receiveds, the second join needs to be a LEFT JOIN and you need to handle the NULLs in your SELECT list -
SELECT
a.*,
ra.receivable,
IFNULL(rd.received, 0) received,
ra.receivable - IFNULL(rd.received, 0) balance
FROM accounts a
INNER JOIN (
SELECT id, SUM(receivable) receivable
FROM receivables
GROUP BY id
) ra
ON a.id = ra.id
LEFT JOIN (
SELECT id, SUM(received) received
FROM receiveds
GROUP BY id
) rd
ON a.id = rd.id
HAVING balance > 0;
You can (and should) go a step further and remove the first derived table as it is unnecessary overhead -
SELECT
a.*,
SUM(ra.receivable) receivable,
IFNULL(SUM(rd.received), 0) received,
SUM(ra.receivable) - IFNULL(rd.received, 0) balance
FROM accounts a
INNER JOIN receivables ra
ON a.id = ra.id
LEFT JOIN (
SELECT id, SUM(received) received
FROM receiveds
GROUP BY id
) rd
ON a.id = rd.id
GROUP BY id
HAVING balance > 0;
db<>fiddle

SQL Query to Return only one row per customer

The database tables I am working with are as the following:
Type_Telephone
ID_Type_Telephone (PK)
Description
0
LandLine
1
Cellular
2
Telecopier
Telephone
ID_Telephone (PK)
ID_Client (FK)
ID_Type_Telephone (FK)
Numero
100
201
0
514-555-0165
101
201
1
514-555-0155
102
202
1
514-555-0176
103
200
0
514-555-0164
104
200
1
514-555-0119
Client
ID_Client (PK)
Nom
Prenom
200
Bertrand
Antoine
201
Legault
Claude
202
Leonard
Sylvie
I would like to write a SQL query that lists all customers' Cellular and Landline telephones. I would like to have only one row of results per customer such as:
Nom
Prenom
Landline
Cellular
Bertrand
Antoine
514-555-0164
514-555-0119
Legault
Claude
514-555-0165
514-555-0155
Leonard
Sylvie
514-555-0176
Any advice how to generate this ? Thank you !
This requires a pivot query, something like this:
SELECT
c.ID_Client,
c.Nom,
c.Prenom,
MAX(CASE WHEN tt.Description = 'LandLine' THEN t.Numero END) AS Landline,
MAX(CASE WHEN tt.Description = 'Cellular' THEN t.Numero END) AS Cellular
FROM Client c
LEFT JOIN Telephone t
ON t.ID_Client = c.ID_Client
LEFT JOIN Type_Telephone tt
ON tt.ID_Type_Telephone = t.ID_Type_Telephone
GROUP BY
c.ID_Client,
c.Nom,
c.Prenom;
If you also want to include possible telecopier numbers, then add another max of CASE expression to the above query.
SELECT c.nom,
c.prenom,
t0.numero landline,
t1.numero cellular
FROM Client c
LEFT JOIN Telephone t0 ON c.id = t0.ID_Client AND t0.ID_Type_Telephone = 0
LEFT JOIN Telephone t1 ON c.id = t1.ID_Client AND t1.ID_Type_Telephone = 1
If you need one more column for Telecopier then add one more table copy.
The query assumes that Telephone (ID_Client, ID_Type_Telephone) is defined as UNIQUE. If not then
SELECT c.nom,
c.prenom,
GROUP_CONCAT(t0.numero) landline,
GROUP_CONCAT(t1.numero) cellular
FROM Client c
LEFT JOIN Telephone t0 ON c.id = t0.ID_Client AND t0.ID_Type_Telephone = 0
LEFT JOIN Telephone t1 ON c.id = t1.ID_Client AND t1.ID_Type_Telephone = 1
GROUP BY 1, 2

How to return customers and additional info who have null in second table

T1 Customers
IDZ NAME MEGAID
123 TOM 32132
124 JEK 32323
125 MAX 32342
126 JIZ 32134
T2 Info:
ID CID GUNS STATUS
1 123 3 1
2 124 4 2
3 126 NULL 1
T3 Status:
ID TYPE
1 Active
2 Inactive
IDZ = CID
I need to return NAME, MEGAID and STATUS (Active/Inactive) for everyone who have NULL on GUNS column from INFO table.
I tried this:
SELECT Customers.Name, CustomersMEGAID, Status.TYPE
FROM Customers
LEFT JOIN Customers ON Info.CID=Custoners.IDZ
WHERE Info.Guns= IS NULL;
But thats doesnt work(
Big thanks if someone can help with this
your question is full with errors but here is a query for you:
SELECT Customers.Name, Customers.MEGAID, Status.TYPE
FROM Customers
LEFT JOIN Info ON Customers.IDZ = Info.CID
INNER JOIN Status ON Info.STATUS = Status.ID
WHERE Info.Guns IS NULL;
You can join all three tables, and then search for nulls in the column.
For example:
select
c.name,
c.megaid,
s.type
from customers c
join info i on i.cid = c.idz
join status s on s.id = i.status
where i.guns is null

How to use cross join with left outer join?

I have to show list of employee who has claim for expense for the particular month, but am getting all employee list.
SELECT employee_id, expense_month, GROUP_CONCAT(CONCAT_WS('=', exp_type_text, monthly_exployee_expense))
FROM
(
SELECT tbl_employee.employee_id, expense_months.expense_month, tbl_expense_type.exp_type_id, tbl_expense_type.exp_type_text, SUM(expense_cost) AS monthly_exployee_expense
FROM tbl_employee
CROSS JOIN tbl_expense_type
CROSS JOIN
(
SELECT DISTINCT DATE_FORMAT(expense_date, '%Y%m') AS expense_month
FROM exp_tbl
) expense_months
LEFT OUTER JOIN exp_tbl
ON tbl_employee.employee_id = exp_tbl.employee_id
AND tbl_expense_type.exp_type_id = some_table.expense_type
AND expense_months.expense_month = DATE_FORMAT(exp_tbl.expense_date, '%Y%m')
GROUP BY tbl_employee.employee_id, expense_months.expense_month, tbl_expense_type.exp_type_id, tbl_expense_type.exp_type_text
) Sub1
GROUP BY employee_id, expense_month
this the query i had.. how to get only expense claimed employee list.
Example out put is:
3 Ramesh Kumar M 201402 Phone Expense=0=16,Consumable Purchase=0=11,Auto=0...
3 Ramesh Kumar M 201403 Consumable Purchase=0=11,Auto=0=6,2 wheeler=0=1,Lo...
3 Ramesh Kumar M 201404 Logistics/Transportation=0=18,Labour=0=13,Fuel=0=8...
3 Ramesh Kumar M 201405 Bus Travel=0=3,Office Vehicle=0=20,Others=0=15,Sta...
4 testexplevel1 201402 Others=0=15,Stay=0=10,Train Travel=0=5,Office Main...
4 testexplevel1 201403 Office Maintenance=0=17,Billable Purchase=0=12,Cal...
4 testexplevel1 201404 Call Taxi=0=7,4 wheeler=0=2,Guest House=0=19,Trans...
In that list not want all employee list. Only show ramesh data. Because that employee only has claimed.
Makes sense. You cross join all employees against all months and all expense types into a big cartesian product. Then you left join the actual expenses, so nothing gets excluded if there are no expenses.
So the quick fix would be to inner join the expenses. Doing so only gives you the employee-months for which an expense exists.
But doing so also allows you to remove the cross joins altogether and change it all to inner joins:
select
emp.employee_id,
DATE_FORMAT(ex.expense_date, '%Y%m'),
GROUP_CONCAT(CONCAT_WS('=', et.exp_type_text, ex.monthly_exployee_expense))
from
tbl_employee emp
inner join exp_tbl ex on ex.employee_id = emp.employee_id
inner join tbl_expense_type et on et.exp_type_id = ex.expense_type
group by
emp.employee_id,
DATE_FORMAT(ex.expense_date, '%Y%m')
Now, isn't that query much cleaner? :)

how to write the select statement in case statement

Let me know how to write select query in case statement.
select
ROW_NUMBER() OVER(Order by vendor.VendorName ) AS ID,
PH.PurchasingHeaderID as BILLNo,
PH.TotalPriceCompanyCurrency as Balance,
acc.AccountName as [Account_Name]
**Into #tempOpenVedorlist**
from PurchasingHeader PH
LEFT OUTER JOIN TransactionType Trans ON PH.TransactionTypeID =Trans.TransactionTypeID
LEFT OUTER JOIN Vendor vendor on PH.VendorID=vendor.VendorID
LEFT OUTER JOIN PaymentTerm PT on PT.PaymentTermID = vendor.PaymentTermID
LEFT OUTER JOIN PurchasingDetail PD on PD.PurchasingHeaderID = PH.PurchasingHeaderI
LEFT OUTER JOIN Account Acc on Acc.AccountID= PD.FinancialAccountID
where PH.TransactionTypeID=7
Group by vendor.VendorName,
PH.PurchasingHeaderID,PH.TotalPriceCompanyCurrency,acc.AccountName
I GOT THIS RESULT :
with this result: Here i have No : VB1003 two times but Account Name is different.
ID BILLNo Account_Name Balance
-------------------------------------------------------------
101 VB1000 Cash-Petty Cash 4000.00
102 VB1001 Accounts Receivable 5000.00
103 VB1003 Cash-PettyCash 6000.00
104 VB1003 Cash 6000.00
105 VB1004 UndepositedFunds 7000.00
Here i have to show ;
I need this result :
ID BILLNo Account_Name Balance
------------------------------------------------------
101 VB1000 Cash-PettyCash 4000.00
102 VB1001 AccountsReceivable 5000.00
103 VB1003 ---Multiple---- 6000.00
104 VB1004 UndepositedFunds 7000.00
For aboue result what i have did : i have taken all the data in temp table.
Am able show Multiple string for which has more than one No.
But unfortunatly am not able show Account Name for which has only one BILLNo.
select ROW_NUMBER() OVER(Order by BILLNo ) AS ID,
[BILLNo],
Balance,
CASE
WHEN count(BILLNo)>1 THEN 'Multipul'
WHEN count(BILLNo)<2 THEN **(Select Account_Name from #tempOpenVedorlist )**
End As [Financial_Account]
from #tempOpenVedorlist
Group By BILLNo,Balance
Let me know how can i get account name from temp table which is related to that BILLNo.
Remove the AccountName from the GROUP BY and put an aggregate on that.
SELECT ROW_NUMBER() OVER(Order by vendor.VendorName ) AS ID,
PH.PurchasingHeaderID as BILLNo,
PH.TotalPriceCompanyCurrency as Balance,
CASE WHEN MIN(acc.AccountName) IS NULL
THEN '----'
WHEN MIN(acc.AccountName) = MAX(acc.AccountName)
THEN MIN(acc.AccountName)
ELSE '--MULTIPLE--'
END as [Account_Name]
INTO #tempOpenVedorlist
FROM PurchasingHeader PH
LEFT OUTER JOIN TransactionType Trans
ON PH.TransactionTypeID =Trans.TransactionTypeID
LEFT OUTER JOIN Vendor vendor
ON PH.VendorID=vendor.VendorID
LEFT OUTER JOIN PaymentTerm PT
ON PT.PaymentTermID = vendor.PaymentTermID
LEFT OUTER JOIN PurchasingDetail PD
ON PD.PurchasingHeaderID = PH.PurchasingHeaderI
LEFT OUTER JOIN Account Acc
ON Acc.AccountID= PD.FinancialAccountID
WHERE PH.TransactionTypeID=7
GROUP BY vendor.VendorName,
PH.PurchasingHeaderID,
PH.TotalPriceCompanyCurrency