Search code examples
sqlsql-serverselectcorrelated-subquery

SELECT using Correlated Sub Queries and multiple tables


I have two tables (Table1 & Table2). One including a date (tDate) column and an ID (tTillNo) column that I would like to group by. And another with values (pValue) that I would like to sum for each date and ID.

The tables can be joined using the 'tName' and 'pName' columns from each table, however the pName column may have duplicates, which I would like to include in the sum. For the 3 sub queries I also need to include the where clauses using the 'pCode' column.

And I would like to return the columns shown here https://imgur.com/nyNmTzs

Using the below code however returns the sub queries with incorrect totals as I am using 'MAX(a.tName)' to prevent the grouping of this field. Could anyone suggest another way of preventing this or an alternative way of going about this query?

SELECT 
    DATENAME(Month,a.tDate) as 'Month Name', DAY(a.tDate) as 'Day', 
    MONTH(a.tDate) as 'Month', YEAR(a.tDate) as 'Year', a.tTillNo,

    BankedCash=(SELECT ISNULL(CAST(SUM(b.pValue) as numeric(12,2)),0) 
               FROM Table2 b 
                    where MAX(a.tName)=b.pName AND pCode = 'CSH' 
                    or pCode = 'CHQ'),

    CardTransactions=(SELECT ISNULL(CAST(SUM(b.pValue) as numeric(12,2)),0) 
                     FROM Table2 b 
                          where MAX(a.tName)=b.pName AND b.pCode = 'CRD'),

    BankingTotal=(SELECT ISNULL(CAST(SUM(b.pValue) as numeric(12,2)),0) 
                 FROM Table2 b 
                      where MAX(a.tName)=b.pName AND b.pCode = 'CSH' or 
                      b.pCode = 'CHQ' or b.pCode = 'CRD')

FROM Table1 a

group by YEAR(a.tDate), MONTH (a.tDate), DATENAME(Month,a.tDate), 
DAY(a.tDate), a.tTillNo

order by YEAR(a.tDate), MONTH (a.tDate), DATENAME(Month,a.tDate)

Any suggestions or article referrals would be highly appreciated. Many thanks in advance.

CREATE TABLE [dbo].[Table1](
[UniqueID] [int] IDENTITY(1,1) NOT NULL,
[tTillNo] [varchar](4) NULL,
[tName] [varchar](20) NULL,
[tDate] [datetime] NULL)

INSERT INTO Table1 (tTillNo, tName, tDate)
VALUES ('0101', '01010000001', '2018-10-30 00:00:00.000'),
       ('0101', '01010000002', '2018-10-30 00:00:00.000'),
       ('0102', '01020000001', '2018-10-30 00:00:00.000'),
       ('0102', '01020000002', '2018-10-30 00:00:00.000')

CREATE TABLE [dbo].[Table2](
[UniqueID] [int] IDENTITY(1,1) NOT NULL,
[pName] [varchar](20) NULL,
[pCode] [varchar](10) NULL,
[pValue] [decimal](22, 7) NULL)


INSERT INTO Table2 (pName, pCode, pValue)
VALUES ('01010000001', 'CRD', '100.0000000'),
       ('01010000002', 'CSH', '100.0000000'),
       ('01020000001', 'CHQ', '100.0000000'),
       ('01020000002', 'CSH', '100.0000000'),
       ('01020000002', 'CRD', '100.0000000'),
       ('01010000001', 'CSH', '100.0000000')

Solution

  • I think you can solve this all with a join.

    select DATENAME(Month,a.tDate) as 'Month Name'
       , DAY(a.tDate) as 'Day'
       , MONTH(a.tDate) as 'Month'
       , YEAR(a.tDate) as 'Year'
       , a.tTillNo
       , BankedCash=SUM(case when pCode in( 'CSH','CHQ') then pvalue else 0 end)
       , [Card] = SUM(case when pCode in( 'CRD') then pvalue else 0 end)
       ,Total = SUM(pvalue)
    from TableA a
        join TableB b on a.tName=b.pName
    group by YEAR(a.tDate)
        , MONTH (a.tDate)
        , DATENAME(Month,a.tDate)
        , DAY(a.tDate)
        , a.tTillNo