Inner Join Taking Forever To Run In Big Query - sql

I have a query that is taking forever to do an inner join. It runs for 6 hours and then times out. The query is:
SELECT
a.*,
b.total_video,
b.total_initial_video,
b.total_discovery,
b.total_sub_video,
b.total_sub_initial_video,
b.total_sub_discovery,
FROM temp_table.source_stage_ a
INNER JOIN temp_table.source_stage2_ b
ON (a.day = b.day
AND a.state_desc = b.state_desc
AND a.package_desc = b.package_desc
AND a.brand = b.v1_brand
))
temp_table.source_stage_ is
create or replace table temp_table.source_stage_ as (
select *,
case
when cycle = 0
then 'Trial'
when cycle = 1
then '1 Month'
when cycle between 2 and 3
then '2 - 3 Months'
when cycle between 4 and 5
then '4 - 5 Months'
when cycle >= 6
then '6+ Months'
end as group,
from(
select
*,
case when active_days < 0 then 0 else cast( ceil( ( case when active_days < 1 then 1 else active_days end ) / 30 ) as int64 ) end cycle, from (
SELECT
t.activation_dt,
t.end_dt,
t.trial_start_dt,
t.start_dt,
date_diff(p.day_dt,coalesce(activation_dt,trial_start_dt,start_dt),DAY) as active_days,
date_diff(p.day_dt,coalesce(start_dt),DAY) as active_days,
p.day_dt,
state_desc,
package_desc,
v1_brand,
sc.scarp_group,
p.last_touch,
SUM(p.video_playback_ind) as video_start_cnt,
SUM(CASE WHEN cd_path_rank_nbr = 1 THEN p.video_playback_ind ELSE 0 END) as initial_video_start_cnt,
SUM(CASE WHEN p.video_playback_ind = 1 AND f.session_nbr IS NOT NULL THEN 1 ELSE 0 END) as discovery_start_cnt,
COUNT(DISTINCT(p.registration_id_nbr)) as sub_video_start_cnt,
COUNT(DISTINCT(CASE WHEN cd_path_rank_nbr = 1 THEN p.registration_id_nbr ELSE NULL END)) as sub_initial_video_start_cnt,
COUNT(DISTINCT(CASE WHEN f.session_nbr IS NOT NULL THEN p.registration_id_nbr ELSE NULL END)) as sub_discovery_start_cnt,
FROM table1 p
LEFT JOIN table2 f
ON p.day_dt = f.day_dt
AND p.session_nbr = f.session_nbr
AND f.day_dt = '2023-02-11'
LEFT JOIN table3 t
on (p.registration_id_nbr = t.user_id_cd
and p.day_dt between t.activation_dt and t.end_dt)
left join table4 as sc
on (p.registration_id_nbr is not null
and sc.user_id_cd is not null
and p.registration_id_nbr = sc.user_id_cd
and p.day_dt between sc.period_start_dt and sc.period_end_dt)
WHERE p.day_dt = '2023-02-11'
AND p.video_playback_ind = 1
AND p.report_suite_id NOT IN ('cb', 'ic', 'bs')
AND LOWER(p.state_desc) IN ("tr", "s", "di of")
AND lower(package_desc) IN ('cf', 'lc', 'lcp', 'cf-s', 'lc-s', 'lcp-s')
AND v1_brand LIKE 'pp_%'
GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12
)))
temp_table.source_stage2_ is
create or replace table temp_table.source_stage2 as (
select *,
case
when tenure_cycle = 0
then 'Trial'
when tenure_cycle = 1
then '1 Month'
when tenure_cycle between 2 and 3
then '2 - 3 Months'
when tenure_cycle between 4 and 5
then '4 - 5 Months'
when tenure_cycle >= 6
then '6+ Months'
end as tenure_group,
from(
select
*,
case when paid_active_days < 0 then 0 else cast( ceil( ( case when paid_active_days < 1 then 1 else paid_active_days end ) / 30 ) as int64 ) end tenure_cycle, from (
SELECT
t.activation_dt,
t.end_dt,
t.trial_start_dt,
t.paid_start_dt,
date_diff(p.day_dt,coalesce(activation_dt,trial_start_dt,paid_start_dt),DAY) as active_days,
date_diff(p.day_dt,coalesce(paid_start_dt),DAY) as paid_active_days,
p.day_dt,
state_desc,
package_desc,
v1_brand_nm,
sc.scarp_group,
SUM(p.video_playback_ind) as total_video,
SUM(CASE WHEN cd_path_rank_nbr = 1 THEN p.video_playback_ind ELSE 0 END) as total_initial_video,
SUM(CASE WHEN p.video_playback_ind = 1 AND f.v88_player_session_nbr IS NOT NULL THEN 1 ELSE 0 END) as total_discovery,
COUNT(DISTINCT(p.v69_registration_id_nbr)) as total_sub_video,
COUNT(DISTINCT(CASE WHEN cd_path_rank_nbr = 1 THEN p.v69_registration_id_nbr ELSE NULL END)) as total_sub_initial_video,
COUNT(DISTINCT(CASE WHEN f.v88_player_session_nbr IS NOT NULL THEN p.v69_registration_id_nbr ELSE NULL END)) as total_sub_discovery,
FROM `table1` p
LEFT JOIN `table2` f
ON p.day_dt = f.day_dt
AND p.v88_player_session_nbr = f.v88_player_session_nbr
AND f.day_dt = '2023-02-11'
LEFT JOIN `table3` t
on (p.registration_id_nbr = t.cbs_reg_user_id_cd
and p.day_dt between t.activation_dt and t.end_dt)
left join `table4` as sc
on (p.registration_id_nbr is not null
and reg_user_id_cd is not null
and p.registration_id_nbr = reg_user_id_cd
and p.day_dt between sc.period_start_dt and sc.period_end_dt)
WHERE p.day_dt = '2023-02-11'
AND p.video_playback_ind = 1
AND p.report_suite_id NOT IN ('cb', 'ic', 'bs')
AND LOWER(p.state_desc) IN ("tr", "s", "di of")
AND lower(package_desc) IN ('cf', 'lc', 'lcp', 'cf-s', 'lc-s', 'lcp-s')
AND v1_brand_nm LIKE 'pp_%'
GROUP BY 1,2,3,4,5,6,7,8,9,10,11
)))
The last two queries, temp_table.source_stage_ and temp_table.source_stage2_ create temp tables and are the same except one column that is added to the first one

Related

How could I adapt this query to work over multiple years?

This query pulls data from a VistaDB and produces info on the number of courses started in each month of the year from people in different countries.
Select c.CountryName As Country,
Count (case When Month( ch.CourseStarted ) = 1 Then 1 End) As Jan19,
Count (case when Month(ch.CourseStarted ) = 2 Then 1 End) as Feb19,
Count (case When Month(ch.CourseStarted ) = 3 Then 1 End) as Mar19,
Count (case When Month(ch.CourseStarted ) = 4 Then 1 End) as Apr19,
Count (case When Month(ch.CourseStarted ) = 5 Then 1 End) as May19,
Count (case When Month(ch.CourseStarted ) = 6 Then 1 End) as Jun19,
Count (case When Month(ch.CourseStarted ) = 7 Then 1 End) as Jul19,
Count (case When Month(ch.CourseStarted ) = 8 Then 1 End) as Aug19,
Count (case When Month(ch.CourseStarted ) = 9 Then 1 End) as Sep19,
Count (case When Month(ch.CourseStarted ) = 10 Then 1 End) as Oct19,
Count (case When Month(ch.CourseStarted ) = 11 Then 1 End)as Nov19,
Count (case When Month(ch.CourseStarted ) = 12 Then 1 End) as Dec19
From Country As c
Inner Join CourseHistory As ch On c.Oid = ch.Country
Where (ch.CourseStarted >= '2019-01-01' And
ch.CourseStarted <= '2019-12-31')
Group By c.CountryName
Order by c.CountryName;
My question is would it be possible to make this semi-dynamic so that if I were to make the final date in the where clause '2022-12-31' I could get a rafft of colums for each month of each year?

Get COUNT with a condition from a joined table

I have a table SyncHistory:
SyncHistoryId SyncType SyncDateTime
-----------------------------------------------------
55 1 2017-11-28 09:30:51.810
56 1 2017-11-28 10:30:32.123
And then another table SyncDetails:
SyndDetailId SyncHistoryId ItemId ItemCreated ItemChanged
---------------------------------------------------------------------------
98 55 12345 1 0
99 55 23183 1 0
100 55 87687 0 1
101 55 23234 0 0
102 55 23222 0 0
103 56 9928 1 0
What I'm trying to do is create a query that gives me this:
Sync Data New Existing & Changed Existing & Not Changed
---------------------------------------------------------------------------
11/28/2017 9:30am 2 1 2
11/28/2017 10:30am 1 0 0
This is what I'm trying:
SELECT
sh.SyncHistoryId
, sh.SyncDateTime
, count(sd1.SyncDetailId) AS Created
, count(sd2.SyncDetailId) AS ExistingChanged
, count(sd3.SyncDetailId) AS ExistingNotChanged
FROM
SyncHistory sh
LEFT JOIN SyncDetails sd1 ON sh.SyncHistoryId = sd1.SyncHistoryId AND sd1.ItemCreated = 1 AND sd1.ItemChanged = 0
LEFT JOIN SyncDetails sd2 ON sh.SyncHistoryId = sd2.SyncHistoryId AND sd2.ItemCreated = 0 AND sd2.ItemChanged = 1
LEFT JOIN SyncDetails sd3 ON sh.SyncHistoryId = sd3.SyncHistoryId AND sd3.ItemCreated = 0 AND sd3.ItemChanged = 0
WHERE
sh.SyncType = 1
GROUP BY
sh.SyncHistoryId
, sh.SyncDateTime
ORDER BY
sh.SyncDateTime DESC
But, none of the resulting counts are accurate. I'm doing something wrong, but not sure what.
SELECT h.SyncDateTime,
SUM(case when d.ItemCreated = 1 then 1 else 0 end) as New,
SUM(case when d.ItemChanged = 1 then 1 else 0 end) as [Existing & Changed],
SUM(case when d.ItemCreated = 0 and d.ItemChanged = 0 then 1 else 0 end) as [Existing & Not Changed]
FROM SyncHistory h
INNER JOIN SyncDetails d ON h.SyncHistoryId = d.SyncHistoryId
GROUP BY h.SyncDateTime
You only need to JOIN to the details table once. You can get your counts from that through aggregation:
SELECT
CONVERT(VARCHAR(16), SH.SyncDateTime, 120) AS SyncTime,
SUM(CASE WHEN SD.ItemCreated = 1 AND SD.ItemChanged = 0 THEN 1 ELSE 0 END) AS New,
SUM(CASE WHEN SD.ItemCreated = 0 AND SD.ItemChanged = 1 THEN 1 ELSE 0 END) AS ExistingAndChanged,
SUM(CASE WHEN SD.ItemCreated = 0 AND SD.ItemChanged = 0 THEN 1 ELSE 0 END) AS ExistingAndNotChanged
FROM
SyncHistory SH
LEFT OUTER JOIN SyncDetails SD ON SD.SyncHistoryID = SH.SyncHistoryID
GROUP BY
CONVERT(VARCHAR(16), SH.SyncDateTime, 120)
You weren't clear on how the grouping/datetime should be determined. What I have is by the minute. If it's supposed to be by the hour on the 1/2 hour mark or something else then you'll need to change that part of the query in the GROUP BY and the first column of the SELECT.
Another solution. I hope it will work - no CASE, no subquery:
SELECT
sh.SyncHistoryId
,sh.SyncDateTime
,COUNT( NULLIF( sd.ItemCreated, 0 ) ) AS Created
,COUNT( NULLIF( sd.ItemCreated, 1 ) + NULLIF( sd1.ItemChanged, 0 ) ) AS ExistingChanged
,COUNT( NULLIF( sd.ItemCreated, 1 ) + NULLIF( sd1.ItemChanged, 1 ) ) AS ExistingNotChanged
FROM
SyncHistory sh JOIN SyncDetails sd ON sh.SyncHistoryId = sd.SyncHistoryId
WHERE
sh.SyncType = 1
GROUP BY
sh.SyncHistoryId
,sh.SyncDateTime
ORDER BY
sh.SyncDateTime DESC
I hope subquery is not forbidden:
SELECT
sh.SyncHistoryId
,sh.SyncDateTime
,(SELECT COUNT(*) FROM SyncDetails sd WHERE sh.SyncHistoryId = sd.SyncHistoryId AND sd.ItemCreated = 1 AND sd1.ItemChanged = 0) AS Created
,(SELECT COUNT(*) FROM SyncDetails sd WHERE sh.SyncHistoryId = sd.SyncHistoryId AND sd.ItemCreated = 0 AND sd1.ItemChanged = 1) AS ExistingChanged
,(SELECT COUNT(*) FROM SyncDetails sd WHERE sh.SyncHistoryId = sd.SyncHistoryId AND sd.ItemCreated = 0 AND sd1.ItemChanged = 0) AS ExistingNotChanged
FROM
SyncHistory sh
WHERE
sh.SyncType = 1
ORDER BY
sh.SyncDateTime DESC

group by and select max with value null

I have a next problem with query
SELECT
T.DETALLE_BECA_ANIO anio,
T.DETALLE_BECA_MES mes,
T.DETALLE_BECA_NIVEL_EDU_ID edu_id,
T.DETALLE_BECA_TRAMO_ID tr_id,
MAX(
CASE
WHEN T.DETALLE_BECA_TIPO_BENE_ID IS NULL
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) mant ,
MAX(
CASE
WHEN T.DETALLE_BECA_TIPO_BENE_ID = 1
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) tras
FROM
(SELECT DETALLE_BECA_NIVEL_EDU_ID,
DETALLE_BECA_BECA_ID,
DETALLE_BECA_TIPO_BENE_ID,
DETALLE_BECA_VALOR,
DETALLE_BECA_MES,
DETALLE_BECA_REGION_ID,
DETALLE_BECA_PROVINCIA_ID,
DETALLE_BECA_ANIO,
DETALLE_BECA_TRAMO_ID,
DETALLE_BECA_COMUNA_ID
FROM TBL_DETALLE_BECAS
WHERE (DETALLE_BECA_TIPO_BENE_ID = 1
OR DETALLE_BECA_TIPO_BENE_ID IS NULL)
and DETALLE_BECA_BECA_ID = 1
and detalle_beca_mes = 3
) T
GROUP BY T.DETALLE_BECA_BECA_ID,
T.DETALLE_BECA_TRAMO_ID,
T.DETALLE_BECA_REGION_ID,
T.DETALLE_BECA_PROVINCIA_ID,
T.DETALLE_BECA_ANIO,
T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID,
T.DETALLE_BECA_COMUNA_ID
ORDER BY T.DETALLE_BECA_BECA_ID,
T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID
output:
"ANIO" "MES" "EDU_ID" "TR_ID" "MANT" "TRAS"
2017 3 2 0.62 0 NULL
2017 3 3 1.24 6 NULL
2017 3 NULL 1.0 NULL 1
I need that sum value where EDU_ID is null with value 2,3 in TR_ID and replace value null in "tras" with value from EDU is null
"ANIO" "MES" "EDU_ID" "TR_ID" "MANT" "TRAS"
2017 3 2 1.62 0 1
2017 3 3 2.24 6 1
I writed query with min(edu_id) or max(edu_id ) but could not solve my problem.
The other thing that occurred to me is to make a join with the same table
First, this makes more sense as your query:
SELECT T.DETALLE_BECA_ANIO as anio, T.DETALLE_BECA_MES as mes,
T.DETALLE_BECA_NIVEL_EDU_ID as edu_id, T.DETALLE_BECA_TRAMO_ID as tr_id,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID IS NULL
THEN NVL(DETALLE_BECA_VALOR, 0)
ELSE 0
END) as mant ,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID = 1
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) tras
FROM TBL_DETALLE_BECAS
WHERE (DETALLE_BECA_TIPO_BENE_ID = 1 OR DETALLE_BECA_TIPO_BENE_ID IS NULL) AND
DETALLE_BECA_BECA_ID = 1 AND
detalle_beca_mes = 3
GROUP BY T.DETALLE_BECA_ANIO, T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID, T.DETALLE_BECA_TRAMO_ID
ORDER BY T.DETALLE_BECA_BECA_ID, T.DETALLE_BECA_MES, T.DETALLE_BECA_NIVEL_EDU_ID;
This eliminates the subquery (unnecessary) and only aggregates by the columns being returned. A proper query might fix your problem.
But, you seem to want to use NULL to be "all" for the other columns. If so, something like this will work:
WITH t as (
SELECT T.DETALLE_BECA_ANIO as anio, T.DETALLE_BECA_MES as mes,
T.DETALLE_BECA_NIVEL_EDU_ID as edu_id, T.DETALLE_BECA_TRAMO_ID as tr_id,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID IS NULL
THEN NVL(DETALLE_BECA_VALOR, 0)
ELSE 0
END) as mant ,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID = 1
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) tras
FROM TBL_DETALLE_BECAS
WHERE (DETALLE_BECA_TIPO_BENE_ID = 1 OR DETALLE_BECA_TIPO_BENE_ID IS NULL) AND
DETALLE_BECA_BECA_ID = 1 AND
detalle_beca_mes = 3
GROUP BY T.DETALLE_BECA_ANIO, T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID, T.DETALLE_BECA_TRAMO_ID
)
SELECT t.ANIO, t.MES, t.EDU_ID,
COALESCE(t.TR_ID, 0) + COALESCE(tnull.TR_ID, 0) as TR_ID,
t.MANT,
COALESCE(t.TRAS, 0) + COALESCE(tnull.TRAS, 0) as TRAS
FROM t LEFT JOIN
(SELECT t.*
FROM t
WHERE t.edu_id IS NULL
) tnull
ON tnull.ANIO = t.ANIO AND tnull.MES = t.MES
WHERE t.edu_id IS NOT NULL
ORDER BY T.DETALLE_BECA_BECA_ID, T.DETALLE_BECA_MES, T.DETALLE_BECA_NIVEL_EDU_ID;

Show only row with highest value

In my query I'm returning number of days a week something occurs. Everything is working fine, with the exception that I'm getting multiple rows returned where I only need the highest. So for example in my query, if the TotalDays is 3, I have a row for 1, 2 and 3. If its 4 then I have rows for 1,2,3 and 4, etc. What do I need to do so that I only get the highest one? I tried using both ROW_NUMBER and MAX but can't seem to figure out how to accomplish this with the CASES.
SELECT Employees.CustomerID, X.*, Customers.ReportID
FROM
(
SELECT
CASE WHEN [M] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Tu] = '1' THEN 1 ELSE 0 END +
CASE WHEN [W] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Th] = '1' THEN 1 ELSE 0 END +
CASE WHEN [F] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Sa] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Su] = '1' THEN 1 ELSE 0 END AS DaysofWeek
FROM
Customers
) X, Employees INNER JOIN ON Employees.EmployeesID = Customers.EmployeesID
GROUP BY Employees.CustomerID, Customers.ReportID, X.DaysofWeek
Few more details on this. For any given EmployeeID there can be unlimited ReportIDs and I want to return all of them but ONLY for where the DaysofWeek is the highest.
So EmployeeID 200 may have report 1001 and 1002 that are returned 2 days a week each. What should shows is
200 2 1001
200 2 1002
However, what is currently showing is:
200 1 1001
200 2 1001
200 1 1002
200 2 1002
Modified the query and added a couple more tables though everything is returning a value of 5.
WITH sub AS(
SELECT Shift1.EmployeeID, X.*, Schedule.Services, Schedule.ReportID
FROM
(
SELECT
CASE WHEN [M] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Tu] = '1' THEN 1 ELSE 0 END +
CASE WHEN [W] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Th] = '1' THEN 1 ELSE 0 END +
CASE WHEN [F] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Sa] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Su] = '1' THEN 1 ELSE 0 END AS DaysofWeek
FROM
Schedule
) X, Shift1 INNER JOIN (Shift2 INNER JOIN Schedule ON Shift2.Shift2ID = Schedule.Shift2ID) ON Shift1.Shift1ID = Shift2.Shift1ID
GROUP BY Shift1.EmployeeID, Schedule.Services, Schedule.ReportID, X.DaysofWeek
)
SELECT X.*
FROM sub X
JOIN (SELECT EmployeeID, ReportID, MAX(DaysofWeek) AS DaysofWeek
FROM sub
GROUP BY EmployeeID, ReportID) Y
ON X.DaysofWeek = Y.DaysofWeek
and X.EmployeeID = Y.EmployeeID
and X.ReportID = Y.ReportID
First, your query should look like:
SELECT e.CustomerID, c.DaysOfWeek, c.ReportId
FROM (SELECT c.*,
(CASE WHEN [M] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Tu] = '1' THEN 1 ELSE 0 END +
CASE WHEN [W] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Th] = '1' THEN 1 ELSE 0 END +
CASE WHEN [F] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Sa] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Su] = '1' THEN 1 ELSE 0 END
) AS DaysofWeek
FROM Customers c
) c JOIN
Employees e
ON e.EmployeesID = c.EmployeesID
GROUP BY e.CustomerID, c.ReportID, c.DaysofWeek;
I question the join (why would Employee.CustomerId not join to the Customers table?), but this is how you have it. To get the reports with the biggest day of the week, use DENSE_RANK():
SELECT e.CustomerID, c.DaysOfWeek, c.ReportId
FROM (SELECT c.*, DENSE_RANK() OVER (PARTITION BY c.EmployeesId ORDER BY DaysOfWeek DESC) as seqnum
FROM (SELECT c.*,
(CASE WHEN [M] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Tu] = '1' THEN 1 ELSE 0 END +
CASE WHEN [W] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Th] = '1' THEN 1 ELSE 0 END +
CASE WHEN [F] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Sa] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Su] = '1' THEN 1 ELSE 0 END
) AS DaysofWeek
FROM Customers c
) c
) c JOIN
Employees e
ON e.EmployeesID = c.EmployeesID
WHERE seqnum = 1
GROUP BY e.CustomerID, c.ReportID, c.DaysofWeek;
The query itself might be able to get cleaned a little better, however if your current query is working and showing you the output you've indicated, but you want to reduce it to what you indicate is your desired output, you should be able to use the with clause to do this as follows:
with sub as(
SELECT Employees.CustomerID, X.*, Customers.ReportID
FROM
(
SELECT
CASE WHEN [M] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Tu] = '1' THEN 1 ELSE 0 END +
CASE WHEN [W] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Th] = '1' THEN 1 ELSE 0 END +
CASE WHEN [F] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Sa] = '1' THEN 1 ELSE 0 END +
CASE WHEN [Su] = '1' THEN 1 ELSE 0 END AS DaysofWeek
FROM
Customers
) X INNER JOIN Employees ON Employees.EmployeesID = Customers.EmployeesID
GROUP BY Employees.CustomerID, Customers.ReportID, X.DaysofWeek
)
select x.*
from sub x
join (select customerid, reportid, max(daysofweek) as daysofweek
from sub
group by customerid, reportid) y
on x.daysofweek = y.daysofweek
and x.customerid = y.customerid
and x.reportid = y.reportid
Also your join clause was off.

Full Join on two queries

I'm trying to do a full join on two SQL queries, below:
1st Query:
SELECT
ID
,SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END) AS TValue
,COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate
GROUP BY ID
2nd Query:
SELECT
ID
,SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END) AS New
,SUM(CASE WHEN reason = 6 THEN 1 ELSE 0 END) AS Amend
,SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2
WHERE Date2 >=#StartDate AND Date2<= #EndDate
GROUP BY ID
Result from query1
ID CountAll TValue
-------------------------
id1 24 1020
id2 13 2030
id3 4 120
Result from query 2:
ID New Amend Cancel
--------------------------------
id1 12 4 6
id2 7 6 1
id4 2 1 2
Needed output:
ID TValue CountAll New Amend Cancel Total(countall+new+amend+cancel)
----------------------------------------------------------------------------------------
Id1 1020 24 12 4 6 46
Id2 2030 13 7 6 1 27
id3 120 4 0 0 0 4
Id4 0 0 2 1 2 5
I'll post my current solution if requested, but it is pretty far from working.
I've been doing a bit of research and I think I need to either make a union to join the ID'S, or just do a Full Join. (Second day ever doing sql)
Try this,
SELECT *
FROM
(
SELECT ID ,
SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END) AS TValue,
COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate
GROUP BY ID
) a FULL JOIN
(
SELECT ID ,
SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END) AS New ,
SUM(CASE WHEN reason = 6 THEN 1 ELSE 0 END) AS Amend ,
SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2
WHERE Date2 >=#StartDate AND Date2<= #EndDate
GROUP BY ID
) b ON a.ID = b.ID
I would write something like below:
select decode (a.id, null, b.id, a.id) as ID, a.TValue, CountAll, b.new, b.Amend, b.cancel
from (SELECT ID ,SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END)
AS TValue ,COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate GROUP BY ID
) a FULL OUTER JOIN
(SELECT ID , SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END)
AS New ,SUM(CASE WHEN reason = 6
THEN 1 ELSE 0 END) AS Amend ,
SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2 WHERE Date2 >=#StartDate AND Date2<= #EndDate GROUP BY ID
) b
on a.id = b.id
have you tried this...
select isnull (a.id,b.id) as ID, a.TValue, CountAll, b.new, b.Amend, b.cancel
from (SELECT ID ,SUM(CASE WHEN reason = 4 THEN 0 ELSE quantity*price END) AS TValue ,COUNT(*) AS CountAll
FROM table1
WHERE Date>=#StartDate AND Date<=#EndDate GROUP BY ID ) a
FULL OUTER JOIN (SELECT ID , SUM(CASE WHEN reason = 1 THEN 1 ELSE 0 END) AS New ,SUM(CASE WHEN reason = 6 THEN 1 ELSE 0 END) AS Amend , SUM(CASE WHEN reason = 5 THEN 1 ELSE 0 END) AS Cancel
FROM Table2 WHERE Date2 >=#StartDate AND Date2<= #EndDate GROUP BY ID ) b on a.id = b.id