SQL Join returning all rows in a table - sql

I am looking to get an account name from a table, but it is returning both rows in the table instead of the one that matches. Here's the table called LEDGERTRANS:
Account Date Voucher
402000 2014-01-14 CM-00011026
554500 2014-01-14 CM-00011026
This is being joined to a table called LEDGERTABLE which will match up the Account based on this tables account number. So we get a voucher number, then the account number, then match that to the table to get the account name. The thing is that this is bringing back BOTH account numbers descriptions from the table. Here's the SQL
SELECT DISTINCT
dbo.CUSTTABLE.NAME AS 'Customer',
dbo.CUSTINVOICEJOUR.INVOICEACCOUNT AS 'Acct #',
dbo.CUSTINVOICEJOUR.SALESID AS 'Sales Order',
dbo.CUSTINVOICEJOUR.INVOICEDATE AS 'Date',
dbo.CUSTINVOICEJOUR.INVOICEID AS 'Invoice',
(INVOICEAMOUNT - SALESBALANCE) AS 'Inv Amt',
'Misc Charge' AS ITEMID,
'Misc. Charge' AS 'Reason',
[DESCRIPTION] AS 'Division',
CREATEDBY
,LEDGERTABLE.ACCOUNTNUM as 'Account Number'
FROM
dbo.CUSTINVOICEJOUR INNER JOIN
dbo.CUSTINVOICETRANS ON dbo.CUSTINVOICEJOUR.INVOICEID = dbo.CUSTINVOICETRANS.INVOICEID INNER JOIN
dbo.CUSTTABLE ON ACCOUNTNUM = dbo.CUSTINVOICEJOUR.INVOICEACCOUNT INNER JOIN
dbo.DIMENSIONS ON NUM = dbo.CUSTINVOICEJOUR.DIMENSION2_
JOIN LEDGERTRANS ON LEDGERTRANS.VOUCHER = CUSTINVOICEJOUR.INVOICEID
inner JOIN LedgerTable ON LedgerTable.ACCOUNTNUM = Ledgertrans.ACCOUNTNUM
WHERE
dbo.CUSTINVOICEJOUR.INVOICEID LIKE 'CM-00%'
AND
dbo.CUSTINVOICEJOUR.INVOICEDATE BETWEEN #start AND #end
AND
dbo.CUSTINVOICEJOUR.DIMENSION2_ IN (#division)
AND
INVOICEAMOUNT <> SALESBALANCE
AND
CREATEDBY IN (#createdBy)
AND
LEDGERTRANS.CREDITING='0'
This effectively brings back 2 entries for each item. How can I get rid of this extra row?
C3 Ingenuity 110051 SO-00670938 CM-00011026 -33.750000000000 Misc Charge 402000
C3 Ingenuity 110051 SO-00670938 CM-00011026 -33.750000000000 Misc Charge 554500
even:
Select LEDGERTABLE.ACCOUNTNUM from LedgerTable JOIN Ledgertrans ON LedgerTable.ACCOUNTNUM = Ledgertrans.ACCOUNTNUM Where LEDGERTRANS.VOUCHER = CUSTINVOICEJOUR.INVOICEID
Returns both results

The difference is the last column (LEDGERTABLE.ACCOUNTNUM if I understand correctly).
You can exclude the table/column from the query, or GROUP BY the rest of columns leaving MIN/MAX from the exisitng account numbers

Related

Error getting the amount grouped by name and account number SQL Server

I have an issue on my SQL query. I tried doing two ways
With the first query I got the right amount but I lose some name descriptions
With the second I got every name descriptions but I got a lower amount.
Context: I want to get the revenue gotten between two dates.
I need the following columns from tables
Table reciboDet I need the columns CtaIngreso, ValorUnitReciboDet
Table CuentaIngreso_A the column nombrectaingreso, ctaingreso (only to create the join)
Table Recibo the columns FechaRecibo and ReciboAnulado
To get the right name descriptions I need to verify the receipt year that was in the table AvpgEnc, but when I do that a lose the amount.
First query
SELECT
ReciboDet.CtaIngreso
, SUM(ReciboDet.ValorUnitReciboDet) AS Total
, CuentaIngreso_A.NombreCtaIngreso
FROM
ReciboDet
INNER JOIN CuentaIngreso_A
ON ReciboDet.CtaIngreso = CuentaIngreso_A.CtaIngreso
WHERE
(ReciboDet.NumRecibo IN
(SELECT NumRecibo
FROM Recibo
WHERE (FechaRecibo BETWEEN '01/10/2020' AND '31/10/2020')
AND (ReciboAnulado = 0)
AND (CuentaIngreso_A.Anio = DATEPART(year, FechaRecibo))
)
)
GROUP BY
ReciboDet.CtaIngreso
, CuentaIngreso_A.NombreCtaIngreso
ORDER BY
CuentaIngreso_A.NombreCtaIngreso
Second query
SELECT
ReciboDet.CtaIngreso [cuenta],
sum(ReciboDet.ValorUnitReciboDet) [monto],
CuentaIngreso_A.NombreCtaIngreso [descripcion]
FROM
ReciboDet
inner join avpgenc
on ReciboDet.NumFactura = AvPgEnc.NumAvPg
inner join CuentaIngreso_A
on ReciboDet.CtaIngreso = CuentaIngreso_A.CtaIngreso
WHERE
(ReciboDet.NumRecibo IN
(SELECT NumRecibo
FROM Recibo
WHERE (FechaRecibo BETWEEN '01/10/2020' AND '31/10/2020')
AND (ReciboAnulado = 0)
)
AND (year(AvPgEnc.FechaVenceAvPg) = CuentaIngreso_A.Anio)
)
GROUP BY
ReciboDet.CtaIngreso
, CuentaIngreso_A.NombreCtaIngreso
ORDER BY
ReciboDet.CtaIngreso

Merging Data to single query

I have two queries one is to get ISSUE and RETURN of Items from table.
select MATU.ITEMNUM ,
MATU.DESCRIPTION ,
MATU.STORELOC ,
MATU.CONDITIONCODE,
MATU.ISSUETYPE,
SUM(MATU.QUANTITY )as QUANTITY,
INV.MINLEVEL,
INV.MAXLEVEL
from MATUSETRANS MATU
LEFT OUTER JOIN Inventory INV
ON INV.ITEMNUM=MATU.ITEMNUM
AND INV.LOCATION=MATU.STORELOC
where MATU.ITEMNUM='H95-04-0010' --A57-01-0459A
AND MATU.TRANSDATE >'01-JAN-19'
AND MATU.CONDITIONCODE='01' and MATU.STORELOC='09'
GROUP BY MATU.ITEMNUM ,MATU.DESCRIPTION ,MATU.STORELOC ,INV.MINLEVEL,INV.MAXLEVEL,MATU.PONUM ,MATU.ISSUETYPE,MATU.CONDITIONCODE;
Which result look like
And My second query is get TRANSFER IN and TRANSFER OUT Items from table
select ITEMNUM ,
DESCRIPTION,
TOSTORELOC ,
FROMSTORELOC ,
--TRANSDATE ,
sum(QUANTITY) as QUANTITY ,
ISSUE_CATEGORY as ISSUETYPE,LOCATION from
(select MATR.ITEMNUM,MATR.DESCRIPTION,MATR.TOSTORELOC,MATR.FROMSTORELOC,MATR.TRANSDATE,MATR.QUANTITY,MATR.ISSUETYPE,
CASE WHEN INV.LOCATION = MATR.FROMSTORELOC THEN 'TRANSFER OUT'
WHEN INV.LOCATION = MATR.TOSTORELOC THEN 'TRANSFER IN'
ELSE '_'END as ISSUE_CATEGORY,
MATR.DOCNUM,INV.LOCATION
from MATRECTRANS MATR
INNER JOIN INVENTORY INV
ON INV.ITEMNUM=MATR.ITEMNUM
where MATR.Itemnum='H95-04-0010' AND MATR.TRANSDATE>'01-JAN-19')
where ISSUE_CATEGORY in ('TRANSFER IN','TRANSFER OUT') and DOCNUM is not null and location='09'
group by ITEMNUM,DESCRIPTION ,TOSTORELOC ,FROMSTORELOC ,ISSUETYPE ,ISSUE_CATEGORY,LOCATION;
Which result look like
When I am trying to join both record look like, record are repeating!
How can i tackle this issue?
I need like this
If theres any TRANSFER IN/OUT values then show them else 0.

Sql Joining 3 Tables Query for Loan Total Result

I have to get the total of Customer Loan from 3 tables the two tables are given loan to sum and the other subtract the paid amount and the tables have Customer ID in common. so far I can get the result only if the Customer ID exist in all tables but if it doesn't exist in one table I won't get Customer in my result. or I get NULL customer IDs when I anchor to the customer.
SELECT
AS1.C_ID AS [Customer ID],
ISNULL(AS1.OldCustomerLoan, 0) AS [Old Loan],
ISNULL(AS2.NewGivenLoan, 0) AS [New Given Loan],
ISNULL(AS3.LoanPaid, 0) AS [PaidLoanAmount],
(ISNULL(AS1.OldCustomerLoan, 0) +
ISNULL(AS2.NewGivenLoan, 0) -
ISNULL(AS3.LoanPaid,0) ) AS Total
FROM
Customer C
LEFT OUTER JOIN
(SELECT
MOC.C_ID,
SUM(MOC.Quantity) AS OldCustomerLoan
FROM
Money_On_Customer MOC (NOLOCK)
GROUP BY
MOC.C_ID) AS1
ON c.C_Id = AS1.C_Id
LEFT OUTER JOIN
(SELECT
NGL.C_ID
,SUM(NGL.G_Take_Loan) AS NewGivenLoan
FROM
Given_Loan NGL
GROUP BY
NGL.C_ID) AS2
ON c.C_Id = AS2.C_Id
LEFT OUTER JOIN
(SELECT
GLP.C_ID, SUM(GLP.G_P_Loan) AS LoanPaid
FROM
Given_Loan_Paid GLP
GROUP BY
GLP.C_ID ) AS3
ON c.C_Id = AS3.C_Id
Here Is a picture of my two results:
When I get NULL Customer IDs
When I don't get All the Customers
You need to use c.c_id for the first column
In order to only get records where they exist in at least one of the tables you can add this to you query, just put you current query in place of the dots, and add the leftid col
Select *
From
(Select c.c_id custonerid,
Coalesce(Coalesce(as1.c_id,as2.c_id),as3.c_id) leftid,......
From ....
) ilv
Where leftid is not null
You might be able to just add
Where coalesce(coalesce(as1.c_id,as2.c_id),as3.c_id) is not null
To then end of your query
#Ab Bennett's answer is right,
because you should use your main(master) table's primary key column
if Customer ID is not available in as1 (Money_On_Customer) it will show null.
Hope you understand my explanation.
UPDATE:
and use following for getting customer id
COALESCE(c.C_Id, AS1.C_Id, AS2.C_Id)
you will get first not null Customer ID
Here is My answer with the help of #Ab Bennett
Select *
From
(
SELECT
C.C_Name AS [Customer ID],
ISNULL(AS1.OldCustomerLoan, 0) AS [Old Loan],
ISNULL(AS2.NewGivenLoan, 0) AS [New Given Loan],
ISNULL(AS3.LoanPaid, 0) AS [PaidLoanAmount],
(ISNULL(AS1.OldCustomerLoan, 0) +
ISNULL(AS2.NewGivenLoan, 0) -
ISNULL(AS3.LoanPaid,0) ) AS Total
FROM
Customer C
LEFT OUTER JOIN
(SELECT
MOC.C_ID,
SUM(MOC.Quantity) AS OldCustomerLoan
FROM
Money_On_Customer MOC (NOLOCK)
GROUP BY
MOC.C_ID) AS1
ON c.C_Id = AS1.C_Id
LEFT OUTER JOIN
(SELECT
NGL.C_ID
,SUM(NGL.G_Take_Loan) AS NewGivenLoan
FROM
Given_Loan NGL
GROUP BY
NGL.C_ID) AS2
ON c.C_Id = AS2.C_Id
LEFT OUTER JOIN
(SELECT
GLP.C_ID, SUM(GLP.G_P_Loan) AS LoanPaid
FROM
Given_Loan_Paid GLP
GROUP BY
GLP.C_ID ) AS3
ON c.C_Id = AS3.C_Id) ilv
Where not ([Old Loan] = 0 and [New Given Loan]=0 and PaidLoanAmount =0 )

Max date won't work, alternative?

I read through some of the answers but couldn't find the right answer for the following question. I have the below query that runs:
SELECT
mbr_src_code as 'C',
cst_recno as 'ID',
ind_first_name as 'FN',
ind_last_name as 'LN',
cst_org_name_dn as 'Company',
cst_ixo_title_dn as 'Title',
MAX(inv_trx_date) as 'Latest Transaction',
inv_add_user as 'User',
pyd_type as 'Type',
bat_code as 'Code',
mbr_add_user 'Add User',
mbr_rejoin_date as 'rejoin',
mbt_code,
adr_state as 'state',
adr_country as 'country',
ivd_amount_cp
FROM
mb_membership
JOIN
co_customer ON cst_key = mbr_cst_key AND mbr_delete_flag = 0
LEFT JOIN
mb_member_type ON mbr_mbt_key = mbt_key
LEFT JOIN
co_customer_x_address ON cxa_key = cst_cxa_key
LEFT JOIN
co_address ON cxa_adr_key = adr_key
LEFT JOIN
co_individual ON ind_cst_key = cst_key
LEFT JOIN
mb_membership_x_ac_invoice ON mxi_mbr_key = mbr_key
LEFT JOIN
ac_invoice ON mxi_inv_key = inv_key
LEFT JOIN
ac_invoice_detail ON ivd_inv_key = inv_key
LEFT JOIN
ac_payment_detail ON pyd_ivd_key = ivd_key
LEFT JOIN
ac_payment ON pyd_pay_key = pay_key
LEFT JOIN
ac_batch ON pay_bat_key = bat_key
LEFT JOIN
ac_payment_info ON pay_pin_key = pin_key
LEFT JOIN
co_customer_x_customer ON cxc_cst_key_1 = co_customer.cst_key
AND (cxc_end_date IS NULL OR DATEDIFF(dd, GETDATE(), cxc_end_date) >= 0)
AND cxc_rlt_code = 'Chapter Member'
LEFT JOIN
co_chapter ON cxc_cst_key_2 = chp_cst_key
WHERE
(mbr_src_code LIKE N'%1DMFY18%' OR mbr_src_code LIKE N'%2DMFY18%'
OR mbr_src_code LIKE N'%INPhoneFY18%' OR mbr_src_code LIKE N'%OBTMFY18%'
OR mbr_src_code LIKE N'%3DMFY18%')
AND cst_recno = '20239'
GROUP BY
mbr_key, mbr_src_code, cst_recno,
ind_first_name, ind_last_name, cst_org_name_dn, cst_ixo_title_dn,
inv_add_user, pyd_type, bat_code, mbr_add_user, mbr_rejoin_date,
mbt_code, adr_state, adr_country, pin_cc_number_display, pin_cc_cardholder_name,
ivd_amount_cp, chp_name
ORDER BY
ind_last_name
and I get the following result(sample):
C ID FN LN Company Title Latest transaction User Type Code Add User rejoin mbt_code state country ivd_amount_cp
2DMFY18 20239 Gus Bauman Beveridge & Diamond Attorney 2013-09-23 00:00:00 Membership Renewal Payment 2013-09-23-ULI-USD-C-SP-01 ULI_Conversion NULL Associate Member DC UNITED STATES 430.00
2DMFY18 20239 Gus Bauman Beveridge & Diamond Attorney 2014-08-04 00:00:00 Membership Renewal Payment 2014-08-04-ULI-USD-C-SP-01 ULI_Conversion NULL Associate Member DC UNITED STATES 430.00
2DMFY18 20239 Gus Bauman Beveridge & Diamond Attorney 2015-09-02 00:00:00 Membership Renewal Payment 2015-09-02-ULI-USD-C-SP-02 ULI_Conversion NULL Associate Member DC UNITED STATES 440.00
2DMFY18 20239 Gus Bauman Beveridge & Diamond Attorney 2016-09-12 00:00:00 Membership Renewal Payment 2016-09-12-ULI-USD-C-SP-01 ULI_Conversion NULL Associate Member DC UNITED STATES 440.00
2DMFY18 20239 Gus Bauman Beveridge & Diamond Attorney 2017-09-22 00:00:00 Membership Renewal Payment 2017-09-22-ULI-USD-C-SP-01 ULI_Conversion NULL Associate Member DC UNITED STATES 440.00
So my MAX function doesn't work(probably because there are other columns with different value,just like in inv_trx_date) , what would be the best alternative to use? I would like to basically take the whole query and select MAX(inv_trx_date) as 'Latest Transaction' per each unique cst_recno as 'ID'.
I think the canonical answer to this question is as follows
with AllData as
(
select ... from ...
where ...
)
select * from allData ad1
inner join
(
select pk1, pk2, pk<n>, max(MaxThing) MaxVal
from AllData
group by pk1, pk2, pk<n>
) as ad2
on (ad1.pk1=ad2.pk1 and ad1.pk2=ad2.pk2 and ad1.pk<n>=ad2.pk<n>
and ad1.MaxThing=ad2.MaxVal)
In your case cst_recno is the PK and inv_trx_date is the MaxThing
MAX works over the entire group you have specified. If you want the MAX aggregation to work for each unique cst_recno then you need to group by only each unique cst_recno.
The issue of duplicate rows is because your CODE and ivd_amount_cp columns contain non-unique values in the recordset. Had they all contained the exact same information, your MAX function would have worked without any problems.
You will have to use a Common Table Expression, as others have suggested. Let's assume you have a table that contains a specific CustomerID, and order dates, as well as a lot of other information. A customer can place multiple orders on the same date, and for whatever reason, we're only interested in the latest order of that customer. However, we do want to see all information related to that order.
The first thing we do is build a CTE to identify which order is the latest:
/* Example table */
CREATE TABLE myOrders
(
OrderID int IDENTITY(1,1)
, CustomerID int
, OrderDate datetime
, ImportantInfo nvarchar(255)
)
;
/* Some test data to work with */
INSERT INTO myOrders
VALUES (
1, '01-01-2017', 'We do not want this row'
), (
1, '01-02-2017', 'We do not want this row either'
), (
1, '01-10-2017', 'Getting closer, but not this one either'
), (
1, '01-10-2017', 'This is the one we want!'
)
;
WITH myMaxOrder AS
(
SELECT CustomerID, MAX(OrderID) AS MaxOrderID
FROM myORders
GROUP BY CustomerID
)
Once you identified the MAX of whatever you need, you then simply use that to identify all the other data you want to retrieve, by using the CTE to join back to the original table using the values you just obtained in the CTE:
SELECT
o.*
FROM
MyOrders o
JOIN myMaxOrder o1 ON o.CustomerID = o1.CustomerID
AND o1.MaxOrderID = o.OrderID

How to perform a count on a set of results

I am trying to perform a count on a set of values but the count is bringing in extra values.
Here is some background information. The following T-SQL query returns the data I need:
SELECT DISTINCT [REQ_INFO].UDAValue as 'UDA value', REQ_INFO.ProjectID,
REQ_INFO.BaselineID, Req_ID
FROM [REQ_INFO]
INNER JOIN [Project_INFO] ON [REQ_INFO].[ProjectID]=[Project_INFO].[ProjectID]
INNER JOIN [Baseline_INFO]ON [REQ_INFO].[BaselineID]=[Baseline_INFO].[BaselineID]
WHERE [Project_INFO].[Name] = 'Address Book'
AND [Baseline_INFO].Name = 'Current Baseline'
AND [UDAName] = 'Requirement Priority'
ORDER BY REQ_INFO.Req_ID
This returns the following data:
How I also need to count how many times each value occurs in the UDA value column. The total sum should be 11 as shown above. However I tried the following code but it is counting extra rows:
SELECT [REQ_INFO].UDAValue as 'UDA value',COUNT (*) as 'UDA Num'
FROM [REQ_INFO]
INNER JOIN [Project_INFO] ON [REQ_INFO].[ProjectID]=[Project_INFO].[ProjectID]
INNER JOIN [Baseline_INFO]ON [REQ_INFO].[BaselineID]=[Baseline_INFO].[BaselineID]
WHERE [Project_INFO].[Name] = 'Address Book'
AND [Baseline_INFO].Name = 'Current Baseline'
AND [UDAName] = 'Requirement Priority'
GROUP BY REQ_INFO.UDAValue
Does anyone have suggestions on what I am doing wrong?
Looks to me like it's most likely the distinct statement from the first query that is causing the difference.
If what you are looking for is the actual counts of the occurances of [REQ_INFO].UDAValue. Then you should remove the distinct clause from the first query to see what the second query is actually counting.
As an alternative you can see the total count of the grouped values of the first query like this, but that is different then both your first and second queries.
SELECT [REQ_INFO].UDAValue as 'UDA value',COUNT (*) as 'UDA Num'
FROM [REQ_INFO]
INNER JOIN [Project_INFO] ON [REQ_INFO].[ProjectID]=[Project_INFO].[ProjectID]
INNER JOIN [Baseline_INFO]ON [REQ_INFO].[BaselineID]=[Baseline_INFO].[BaselineID]
WHERE [Project_INFO].[Name] = 'Address Book'
AND [Baseline_INFO].Name = 'Current Baseline'
AND [UDAName] = 'Requirement Priority'
GROUP BY REQ_INFO.UDAValue, REQ_INFO.ProjectID, REQ_INFO.BaselineID, Req_ID
It's hard to tell from your question if that's what you want either. If you truly want a count of the values from the first query as they appear (distinct statement affecting the 4 columns and all). Then you'd probably approach it with a subquery.
Change your count to include a distinct; something like this:
SELECT [REQ_INFO].UDAValue as 'UDA value',COUNT (DISTINCT REQ_INFO.Req_ID) as 'UDA Num'
... rest of your query
I was able to get round the problem by creating a temporary table to allow me to perform the count. This is the SQL statement that I used:
DECLARE #UDAcount TABLE (UDAValue nvarchar(max), ProjectID int,
BaselineID int, Req_ID int, Version nvarchar(128))
INSERT INTO #UDAcount (UDAValue, ProjectID, BaselineID, Req_ID, Version)
SELECT DISTINCT [REQ_INFO].UDAValue as 'UDA value', REQ_INFO.ProjectID,
REQ_INFO.BaselineID, Req_ID, REQ_INFO.Version
FROM [REQ_INFO]
INNER JOIN [Project_INFO] ON [REQ_INFO].[ProjectID]=[Project_INFO].[ProjectID]
INNER JOIN [Baseline_INFO]ON [REQ_INFO].[BaselineID]=[Baseline_INFO].[BaselineID]
WHERE [Project_INFO].[Name] = 'Address Book'
AND [Baseline_INFO].Name = 'Current Baseline'
AND [UDAName] = 'Requirement Priority'
ORDER BY REQ_INFO.Req_ID
SELECT UDAValue as 'UDA value',COUNT (*) as 'UDA Num'
FROM #UDAcount
GROUP BY UDAValue
It may not be the most elegant solution but it does return the desired results. If you have any suggestions on how to improve on this I'd be glad to hear them.