four queries in one result - oracle - sql

I have four queries.
1.result: Count() | Nazev
result: Count() | Nazev
result: Ode_dne_včetně | Do_dne_včetně | Nazev_organizace | Pocet
result: Nazev | Create_uzivatel | create_cas
I want to have only one result after one click. In this way:
Count() | Nazev | Count() | Nazev | Ode_dne_včetně | Do_dne_včetně | Nazev_organizace | Pocet | Nazev | Create_uzivatel | create_cas
Is it possible?
--first
select count(*),subjekt.nazev from osoba,subjekt where
osoba.ID_PATRI_DO=subjekt.ID group by subjekt.nazev order by
subjekt.nazev;
--second
select count(*),subjekt.nazev from ZADAVACI_POSTUP,subjekt where
ZADAVACI_POSTUP.id_zadavatel=subjekt.ID group by subjekt.nazev order by
subjekt.nazev;
--third
select max(trunc(sysdate)-6) ode_dne_včetně, max(trunc(sysdate))
do_dne_včetně,nazev_organizace,count(*) pocet
from(
select to_char(t.popis) popis_typu,subj.nazev nazev_organizace,
u.username,u.nazev, a.datumzapisauditu
,to_char(a.datumzapisauditu,'DD.MM.YYYY') datum , a.id
from d$caudit a
join cuzivatel u on u.id= a.id_uzivatel
join osoba os on u.id_osoba_bridge = os.id
join t$subjekt subj on subj.id = os.id_patri_do
left join d$caudittyp t on t.id=a.id_audittyp
where datumzapisauditu between trunc(sysdate)-7 AND trunc(sysdate)
order by a.datumzapisauditu desc
)
group by nazev_organizace order by nazev_organizace ;
--fourth
select sb.nazev, lg.create_uzivatel, lg.create_cas from Aplikacni_log lg
join zadavaci_postup zp on zp.id = lg.id_zp
join subjekt sb on sb.id = zp.id_zadavatel
where lg.create_cas > to_date('08.11.2014', 'DD.MM.YYYY')
order by sb.nazev asc

You can use subquery refactoring to achieve this.
Edit1:- subjekt.nazev is the relationship between the four queries then
you can add WHERE first_qry.nazev=second_qry.nazev and similar relationship with remaining queries.
with first_qry as (select count(*),subjekt.nazev from osoba,subjekt where
osoba.ID_PATRI_DO=subjekt.ID group by subjekt.nazev order by
subjekt.nazev),
second_qry as (select count(*),subjekt.nazev from ZADAVACI_POSTUP,subjekt where
ZADAVACI_POSTUP.id_zadavatel=subjekt.ID group by subjekt.nazev order by
subjekt.nazev),
third_qry as ( select max(trunc(sysdate)-6)
ode_dne_včetně, max(trunc(sysdate))
do_dne_včetně,nazev_organizace,count(*) pocet
from(
select to_char(t.popis) popis_typu,subj.nazev nazev_organizace,
u.username,u.nazev, a.datumzapisauditu
,to_char(a.datumzapisauditu,'DD.MM.YYYY') datum , a.id
from d$caudit a
join cuzivatel u on u.id= a.id_uzivatel
join osoba os on u.id_osoba_bridge = os.id
join t$subjekt subj on subj.id = os.id_patri_do
left join d$caudittyp t on t.id=a.id_audittyp
where datumzapisauditu between trunc(sysdate)-7
AND trunc(sysdate)
order by a.datumzapisauditu desc
)
group by nazev_organizace order by nazev_organizace),
fourth_qry as (select sb.nazev, lg.create_uzivatel,
lg.create_cas from Aplikacni_log lg
join zadavaci_postup zp on zp.id = lg.id_zp
join subjekt sb on sb.id = zp.id_zadavatel
where lg.create_cas > to_date('08.11.2014', 'DD.MM.YYYY')
order by sb.nazev asc)
select distinct a.*,b.*,c.*,d.*
from first_qry a ,second_qry b,third_qry c,fourth_qry d

Yesterday you asked a similar question and I answered it with this answer.
You can use the same method of using Union or Union all and just select null for each column where you do not have a result
select count(*) AS subjekt_count,subjekt.nazev ,null,null,null,null,null,null
--null columns represent the results from the other queries
from osoba,subjekt
where osoba.ID_PATRI_DO=subjekt.ID
group by subjekt.nazev
UNION ALL
select null, null,count(*) AS subjekt_nazev_count,subjekt.nazev,null,null,null,null
from ZADAVACI_POSTUP,subjekt where
ZADAVACI_POSTUP.id_zadavatel=subjekt.ID
group by subjekt.nazev
---and so on
There are other methods using a WITH statement but you need a common key between the statements and I am not clear on whether your queries are four exclusive queries to the same tables or four overlapping queries. Do you expect duplicates in the results?

All your queries contain column nazev which is grouping and order key so I assumed that this is the field joining results.
If this is so, then you can use follwoing SQL. If this is not what you wanted then please edit question, attach some data, table definitions, preferably as SQL Fiddle and precisely explain your request.
SQLFiddle
with q1 as (select count(*) cnt, subjekt.nazev
from osoba,subjekt where osoba.ID_PATRI_DO=subjekt.ID
group by subjekt.nazev ),
q2 as (select count(*) cnt, subjekt.nazev
from ZADAVACI_POSTUP, subjekt
where ZADAVACI_POSTUP.id_zadavatel=subjekt.ID
group by subjekt.nazev ),
q3 as (select max(trunc(sysdate)-6) ode_dne_vcetne,
max(trunc(sysdate)) do_dne_vcetne, nazev_organizace nazev, count(*) pocet
from (
select to_char(t.popis) popis_typu,subj.nazev nazev_organizace,
u.username, u.nazev, a.datumzapisauditu,
to_char(a.datumzapisauditu,'DD.MM.YYYY') datum, a.id
from d$caudit a
join cuzivatel u on u.id= a.id_uzivatel
join osoba os on u.id_osoba_bridge = os.id
join t$subjekt subj on subj.id = os.id_patri_do
left join d$caudittyp t on t.id=a.id_audittyp
where datumzapisauditu between trunc(sysdate)-7 and trunc(sysdate) )
group by nazev_organizace),
q4 as (select sb.nazev, lg.create_uzivatel, lg.create_cas
from aplikacni_log lg join zadavaci_postup zp on zp.id = lg.id_zp
join subjekt sb on sb.id = zp.id_zadavatel
where lg.create_cas > to_date('08.11.2014', 'DD.MM.YYYY') )
select nazev, q1.cnt cnt1, q2.cnt cnt2, q3.ode_dne_vcetne, q3.do_dne_vcetne,
q3.pocet, q4.create_uzivatel, q4.create_cas
from q1 left join q2 using (nazev) left join q3 using (nazev) left join q4 using (nazev)
order by nazev, create_cas
Output for sample data:
NAZEV CNT1 CNT2 ODE_DNE_VCETNE DO_DNE_VCETNE POCET CREATE_UZIVATEL CREATE_CAS
---------- ---- ---- -------------- ------------- ----- --------------- ----------
SUBJEKT1 1 1 1 2015-03-20
SUBJEKT2 2 1 1 2015-03-20

Related

Is there a way to join two queries in SQL each with an order by?

I have two queries that return data from two tables:
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM
AIRPORT AE
INNER JOIN
FLY V ON V.id_destiny = AE.id
INNER JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) DESC;
Example of returned data:
id
name
number of reserves
6
name1
27
4
name2
18
14
name3
14
and
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM
AEROPUERTO AE
LEFT JOIN
FLY V ON V.id_destiny = AE.id
LEFT JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) ASC;
Example of data returned from this second query:
id
name
number of reserves
7
name4
0
11
name5
0
12
name6
0
I need to combine these into a single output with the first query first (in the same order) and the second query next with the same order like this:
id
name
number of reserves
6
name1
27
4
name2
18
14
name3
14
7
name4
0
11
name5
0
12
name6
0
Is there a way to do it?
Edit: I have already tried the union all option, but I can't use the group by in each query so the table that is returned is different from what I need
(SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM AIRPORT AE
INNER JOIN FLY V
ON V.id_destiny = AE.id
INNER JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.name)
UNION ALL
(SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM AEROPUERTO AE
LEFT JOIN FLY V
ON V.id_destiny= AE.id
LEFT JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.name)
ORDER BY COUNT(R.id) ASC;
When you enclosed each query in parenthesis, it is acting like a derived table. You will need a SELECT clause to select from the derived table.
SELECT *
FROM
(
-- Your first query here
) AS Q1
UNION ALL
SELECT *
FROM
(
-- Your second query here
) AS Q2
You may also use CTE to do it
WITH
Q1 AS
(
-- Your first query here
),
Q2 AS
(
-- Your second query here
)
SELECT *
FROM Q1
UNION ALL
SELECT *
FROm Q2
EDIT : if you also wanted the final result in the same order in both query, add another column for final query ORDER BY
WITH
Q1 AS
(
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves',
Q = 1,
RN = ROW_NUMBER() OVER (ORDER BY COUNT(R.id) DESC)
FROM
AIRPORT AE
INNER JOIN
FLY V ON V.id_destiny = AE.id
INNER JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) DESC
),
Q2 AS
(
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves',
Q = 2,
RN = ROW_NUMBER() OVER (ORDER BY COUNT(R.id) DESC)
FROM
AEROPUERTO AE
LEFT JOIN
FLY V ON V.id_destiny = AE.id
LEFT JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) ASC
)
SELECT *
FROM Q1
UNION ALL
SELECT *
FROM Q2
ORDER BY Q, RN
I break the query and made two temp tables. You can do this in CTE (Commn Table expression) as well.
SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
INTO #Temp_1
FROM AIRPORT AE
INNER JOIN FLY V
ON V.id_destiny = AE.id
INNER JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.name
SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
into #Temp_2
FROM AEROPUERTO AE
LEFT JOIN FLY V
ON V.id_destiny= AE.id
LEFT JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.nam
SELECT *
FROM #Temp_1
UNION ALL
SELECT *
FROM #Temp_2
drop table #Temp_1
drop table #Temp_2

SQL DATEDIFF Returns

I don't want to show my whole query as it is very specific but I will try to explain briefly.
The following query works perfectly and I got 6000 records as a result.
SELECT
DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
However, when i add a DATEDIFF calculation I get only 100 Rows in the answer:
SELECT DISTINCT
ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P,
DATEDIFF(dd,A.ADATE,A.BDATE)
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
I am expecting 6000 rows with a correct query using DATEDIFF in line with what the following query returns:
SELECT
DISTINCT *,
DATEDIFF(dd,A.ADATE,A.BDATE)
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
But I do not need all of them I need just the selected ones and the DATEDIFF but combining the queries above did not work for some reason that i do not know. Can anyone see why i am not getting the expected row count in my second query?
You can just wrap your query in a CTE and perform the DATEDIFF on the result set returned by the CTE:
WITH DISTINCT_CTE AS (
SELECT
DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
)
SELECT *, DATEDIFF(dd, ADATE, BDATE)
FROM DISTINCT_CTE
You could try a subquery... first subquery the entire thing.
In the receiving query do another subquery for the DATEDIFF. For this subquery you need the primary key to get back to the correct row for the dates, which if I'm interpreting correctly is A.ID.
SELECT dT.ID, dT.Name, dT.A_Whatever
,(SELECT DATEDIFF(dd, A2.ADATE, A2.BDATE)
FROM A AS A2
WHERE dT.ID = A2.ID --the primary key
) AS [DateDiff]
--AND SO ON........
FROM (
SELECT DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
) AS dT
You can try the following query :
SELECT T1.*, T2.DateDiff
FROM (
SELECT DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN B ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
) AS T1
JOIN (SELECT ID, DATEDIFF(dd, ADATE, BDATE) as DateDiff from A as A2) AS T2
ON T1.ID= T2.ID
As the following attempts to display, if you are using select distinct AND removing date columns from view when introducing datediff() into the select clause that could be the cause of the change in rows returned. Note in query 1 that as long as adate or bdate are displayed 5 rows would be returned, but without them (query 2) you just get one row. Alternatively, if you removed distinct,from query 2 you would get all 5 rows but just the one column (this isn't shown below).
try it out at SQL Fiddle
MS SQL Server 2014 Schema Setup:
CREATE TABLE Sample
([ADATE] datetime, [BDATE] datetime)
;
INSERT INTO Sample
([ADATE], [BDATE])
VALUES
('2017-10-01 00:00:00', '2017-10-06 00:00:00'),
('2017-10-02 00:00:00', '2017-10-07 00:00:00'),
('2017-10-03 00:00:00', '2017-10-08 00:00:00'),
('2017-10-04 00:00:00', '2017-10-09 00:00:00'),
('2017-10-05 00:00:00', '2017-10-10 00:00:00')
;
Query 1:
select distinct 'q1' qry, adate, bdate, datediff(day,adate,bdate) days_diff
from sample
order by adate
Results:
| qry | adate | bdate | days_diff |
|-----|----------------------|----------------------|-----------|
| q1 | 2017-10-01T00:00:00Z | 2017-10-06T00:00:00Z | 5 |
| q1 | 2017-10-02T00:00:00Z | 2017-10-07T00:00:00Z | 5 |
| q1 | 2017-10-03T00:00:00Z | 2017-10-08T00:00:00Z | 5 |
| q1 | 2017-10-04T00:00:00Z | 2017-10-09T00:00:00Z | 5 |
| q1 | 2017-10-05T00:00:00Z | 2017-10-10T00:00:00Z | 5 |
Query 2:
select distinct 'q2' qry, datediff(day,adate,bdate) days_diff
from sample
Results:
| qry | days_diff |
|-----|-----------|
| q2 | 5 |

Count Customers based on item master

I need you to help me on writing two queries in SQL Server 2008 that shows the following information based on item master:
Brand wise count on customer master plus customer who purchased the brand
Item Wise count of customer master plus customer who purchased the item
Here the link that shows the table information and the query which I tried.
Click here to view the table in SQL Fiddle
SELECT
brandname,
division,
route,
DivisionTotalCustomersCount = MAX(DivisionTotalCustomersCount),
RouteTotalCustomersCount = MAX(RouteTotalCustomersCount),
PurchasedCustomersCount = SUM(PurchasedCustomersCount)
FROM
(SELECT
i.brandname,
c.division,
c.route,
DivisionTotalCustomersCount =
(SELECT COUNT(distinct x.CustomerID)
FROM CustomerMaster x
WHERE x.division = c.division),
RouteTotalCustomersCount =
(SELECT COUNT(distinct x.CustomerID)
FROM CustomerMaster x
WHERE x.Route = c.route),
PurchasedCustomersCount = count(distinct C.CustomerID)
FROM CustomerMaster c
LEFT OUTER JOIN SalesData s on c.CustomerID = s.CustomerID
right outer join ItemMaster i on s.item = i.itemcode
GROUP BY i.brandname, c.division, c.route) A
GROUP BY
brandname, division, route
ORDER BY 1
Result Should as below
Excelsheet
I think you need to go reconsider the report and maybe splitting it out into multiple reports.
It does not make sense to have a route count as well as a divisional count if they are counting things at different levels of aggregation. So have a route count and division count report.
Either way, division and route is going to be null for 100PLUS because there are no customers for that brand which means there is no route or division info available.
--Division Count
SELECT BrandName, Division, COUNT(CustomerMaster.CustomerID) [Customer Count]
FROM ItemMaster LEFT OUTER JOIN
SalesData ON ItemMaster.BrandName = SalesData.Brand LEFT OUTER JOIN
CustomerMaster ON SalesData.CustomerID = CustomerMaster.CustomerID
GROUP BY BrandName, Division
--Route Count
SELECT BrandName, Route, Division, COUNT(CustomerMaster.CustomerID) [Customer Count]
FROM ItemMaster LEFT OUTER JOIN
SalesData ON ItemMaster.BrandName = SalesData.Brand LEFT OUTER JOIN
CustomerMaster ON SalesData.CustomerID = CustomerMaster.CustomerID
GROUP BY BrandName, Route, Division
Using your sqlfiddle data there are 25 sales records & 18 distinct brand/ division/ route/ customer records and there are no sales invloving 100PLUS
select
B.BrandName
, V.Division
, coalesce(Brand_count,0) as Brand_count
, coalesce(Division_count,0) as Division_count
from (select distinct BrandName from ItemMaster) as B
cross join (select distinct Division from CustomerMaster) as V
left join (
select
Brand
, Division
, sum(cust_count) over (partition by Brand) as Brand_count
, sum(cust_count) over (partition by Division) as Division_count
from (
select
S.Brand
, C.Division
, count(distinct S.CustomerID) cust_count
from salesdata as S
inner join CustomerMaster as C
on S.CustomerID = C.CustomerID
inner join ItemMaster as I
on S.item = I.ItemCode
group by
S.Brand
, C.Division
) as S
) as D
on B.BrandName = D.Brand
and V.Division = D.Division
order by
B.BrandName
, V.Division
;
| BRANDNAME | DIVISION | BRAND_COUNT | DIVISION_COUNT |
|-----------|----------|-------------|----------------|
| 100PLUS | Dubai | 0 | 0 |
| 100PLUS | RAK | 0 | 0 |
| KITCO | Dubai | 9 | 11 |
| KITCO | RAK | 9 | 7 |
| Red Bull | Dubai | 9 | 11 |
| Red Bull | RAK | 9 | 7 |
http://sqlfiddle.com/#!3/fecb0/27
All Credit to #kevriley
select
A.BrandName,
B.Division,
B.Route,
B.DivisionTotalCustomers,
B.RouteTotalCustomers,
isnull(C.PurchasedCustomersCount,0) as PurchasedCustomersCount
from
(
select distinct
BrandName, Route, Division
from dbo.ItemMaster
cross join dbo.CustomerMaster
) A
join
(
select distinct
Division,
Route,
DENSE_RANK() over (partition by Division order by c.CustomerID asc) + DENSE_RANK() over (partition by Division order by c.CustomerID desc) - 1 as DivisionTotalCustomers ,
DENSE_RANK() over (partition by ROUTE order by c.CustomerID asc) + DENSE_RANK() over (partition by ROUTE order by c.CustomerID desc) - 1 as RouteTotalCustomers
from CustomerMaster c
left join SalesData s on c.CustomerID = s.CustomerID
) B on B.Division = A.Division and B.Route = A.Route
left join
(
select
s.brand,
c.division,
c.route,
PurchasedCustomersCount = count(distinct C.CustomerID)
FROM CustomerMaster c
JOIN SalesData s on c.CustomerID = s.CustomerID
--join ItemMaster i on s.item = i.itemcode
GROUP by s.brand, c.division, c.route
) C on A.Brandname = C.Brand and C.Division = A.Division and C.Route = A.Route
See the same on SQL Fiddle
Select B.Brandname,B.Division,C AS DivisionTotalCustomerCount,
ISNULL(T.Count,0) AS PURCHASEDCUSTOMERSCOUNT
from
(
Select CM.Division,M.BrandName,COUNT(distinct CM.CustomerID) AS C
from dbo.CustomerMaster CM
CROSS JOIN ItemMaster M
GROUP BY CM.Division,M.BrandName
)B
LEFT JOIN
(Select Division,Brand,COUNT(Distinct C.CustomerID) As Count from CustomerMaster C
JOIN salesdata D
On C.CustomerID=D.CustomerID
where D.Brand='Red Bull'
GROUP BY Division,Brand
)T
ON B.Brandname=T.Brand
and B.Division=T.Division
Order by 1,2

Merging two tables into one both the table having different where clause

I am having Two Sql Queries as Follows:
1st Query
SELECT TC.TCName,
sum(BS.BLDOS) as BLDOS,
sum(BS.CollectedAmount) as CollectedAmount,
(0.35*sum(BS.BLDOS)) as TargetAmount
FROM [Customer] C
INNER JOIN [dbo].[BillingStatus] BS ON BS.CustomerID = C.CustomerID
INNER JOIN [dbo].[TCDetails] TC ON TC.CustomerID = BS.CustomerID
WHERE TC.TCName in (Select distinct(TCName)
FROM [dbo].[TCDetails] )
GROUP BY TCName
order by [TCName] ASC
I am getting a result:
||TCName || BLDOS || CollectedAmount || TargetAmount||
| Aarti | 81234.2 | 1678.76 | 789065 |
| Dev | 181234.2| 678.76 | 2389065 |
2nd query is:
SELECT COUNT(*) as count
FROM [dbo].[TCDetails]
where TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
AND CallDate is NOT NULL
GROUP BY TCName
AND I am Getting:
||count||
231
123
I want to print it like this
||TCName || BLDOS || CollectedAmount || TargetAmount|| count ||
| Aarti | 81234.2 | 1678.76 | 789065 | 231 |
| Dev | 181234.2| 678.76 | 2389065 | 123 |
I am confused because both the queries are having different wheres clause
Try this
SELECT * FROM
(
SELECT TC.TCName, sum(BS.BLDOS) as BLDOS, sum(BS.CollectedAmount) as CollectedAmount, (0.35*sum(BS.BLDOS)) as TargetAmount
FROM [Customer] C INNER JOIN
[dbo].[BillingStatus] BS ON BS.CustomerID = C.CustomerID INNER JOIN
[dbo].[TCDetails] TC ON TC.CustomerID = BS.CustomerID
WHERE TC.TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
GROUP BY TCName order by [TCName] ASC
) S JOIN
(
SELECT TCName,COUNT(*) as count FROM [dbo].[TCDetails]
where TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
AND CallDate is NOT NULL GROUP BY TCName
) T ON S.TCName=T.TCName;
OP:
+--------------------------------------------------------------+
|TCName | BLDOS | CollectedAmount | TargetAmount| count |
+--------------------------------------------------------------+
| Aarti | 81234.2 | 1678.76 | 789065 | 231 |
| Dev | 181234.2| 678.76 | 2389065 | 123 |
+--------------------------------------------------------------+
In both queries you use TCDetails and group by TCName. You don't have to do this twice only to count non-null call dates. COUNT(CallDate) does that for you. I also removed the IN clause which doesn't add anthing to your query. So the query is simply:
SELECT
TC.TCName,
sum(BS.BLDOS) as BLDOS,
sum(BS.CollectedAmount) as CollectedAmount,
0.35 * sum(BS.BLDOS) as TargetAmount,
count(TC.CallDate) as cnt
FROM [Customer] C
INNER JOIN [dbo].[BillingStatus] BS ON BS.CustomerID = C.CustomerID
INNER JOIN [dbo].[TCDetails] TC ON TC.CustomerID = BS.CustomerID
GROUP BY TC.TCName
ORDER BY TC.TCName ASC;
SELECT TC.TCName, sum(BS.BLDOS) as BLDOS, sum(BS.CollectedAmount) as CollectedAmount, (0.35*sum(BS.BLDOS)) as TargetAmount ,
(SELECT COUNT(*) as count FROM [dbo].[TCDetails] TC2
where TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
AND CallDate is NOT NULL AND TC2.TCName = TC.TCName GROUP BY TCName) AS Count
FROM [Customer] C
INNER JOIN [dbo].[BillingStatus] BS
ON BS.CustomerID = C.CustomerID
INNER JOIN [dbo].[TCDetails] TC
ON TC.CustomerID = BS.CustomerID
WHERE TC.TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
GROUP BY TCName order by [TCName] ASC
Try as:
SELECT TC.TCName,
sum(BS.BLDOS) as BLDOS,
sum(BS.CollectedAmount) as CollectedAmount,
(0.35*sum(BS.BLDOS)) as TargetAmount,
Count(CallDate) as count
FROM [Customer] C
INNER JOIN [dbo].[BillingStatus] BS ON BS.CustomerID = C.CustomerID
INNER JOIN [dbo].[TCDetails] TC ON TC.CustomerID = BS.CustomerID
WHERE TC.TCName in (Select distinct(TCName)
FROM [dbo].[TCDetails] )
GROUP BY TCName
order by [TCName] ASC
Check Demo here.
Try below:
SELECT S.*,T.count FROM
(
SELECT TC.TCName, sum(BS.BLDOS) as BLDOS, sum(BS.CollectedAmount) as CollectedAmount, (0.35*sum(BS.BLDOS)) as TargetAmount
FROM [Customer] C JOIN
[dbo].[BillingStatus] BS ON BS.CustomerID = C.CustomerID JOIN
[dbo].[TCDetails] TC ON TC.CustomerID = BS.CustomerID
WHERE TC.TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
GROUP BY TCName order by [TCName] ASC
) S join
(
SELECT TCName,COUNT(*) as count FROM [dbo].[TCDetails]
where TCName in (Select distinct(TCName) FROM [dbo].[TCDetails] )
AND CallDate is NOT NULL GROUP BY TCName
) T on S.TCName=T.TCName;

Select Distinct Records for min date

I Have a query where In I need to select all the distinct ID's from the table, also need to select only the min(date) so that I get records that were inserted 1st and not ID's for all dates.
Basically this is what I am looking for -
Table 1 || Table 2-
ID || ID Date
1 || 1 11/11/2010
1 || 1 10/11/2010
3 || 3 12/01/2010
4 || 4 01/01/2010
4 || 4 02/01/2010
So i need to get all records from Table 2(table1.ID=table2.ID) which has the Minimum Date along with that ID
Result here would be
1 10/11/2010
3 12/01/2010
4 01/01/2010
Here is my query
select u.firstName,u.lastName ,count(*) as theCount
from tbl_appts_change_log c,tbl_appts a, tbl_users u
where c.appt_id=a.ID
and c.user_id=u.userID
and c.appt_id in ( select c.appt_id,min(c.date) from tbl_appts_change_log c, tbl_appts a
where c.appt_id=a.ID
and a.satellite_id='160' GROUP BY c.appt_id)
group by u.firstName,u.lastName
order by count(*) desc,u.firstName,u.lastName
maybe:
select u.firstName,u.lastName ,count(*) as theCount
from tbl_appts_change_log c
INNER JOIN tbl_appts a on c.appt_id=a.ID
INNER JOIN tbl_users u on c.user_id=u.userID
INNER JOIN ( select c.appt_id,min(c.date) as LastDate
from tbl_appts_change_log c
INNER JOIN tbl_appts a on c.appt_id=a.ID
Where a.satellite_id='160' GROUP BY c.appt_id) d
on c.appt_id = d.appt_id and c.date = d.LastDate
group by u.firstName,u.lastName
order by count(*) desc,u.firstName,u.lastName
I am ignoring your code as it seems to be a completely different scenario from what you have described in your question i.e Table1 and Table2. If all you want is the minimum date for each ID all you need is
SELECT T1.ID, MIN(T2.Date)
FROM Table1 T1
JOIN Table2 T2 ON T1.ID = T2.ID
GROUP BY T1.ID
But i am guessing what you really wanted was something like this?
Table 1 || Table 2-
ID || ID Date Desc
1 || 1 11/11/2010 AAA
1 || 1 10/11/2010 BBB
3 || 3 12/01/2010 CCC
4 || 4 01/01/2010 DDD
4 || 4 02/01/2010 EEE
And the expected result
1 10/11/2010 BBB
3 12/01/2010 CCC
4 01/01/2010 DDD
This is slightly more complicated than just doing a group by, and there are two ways to solve it. You could try both and see which one performs best
Method 1 : Using Row number
;WITH ResultCTE AS
(
SELECT T2.ID, T2.Date, T2.Desc,
RowNumber = ROW_NUMBER() OVER(PARTITION BY T2.ID ORDER BY T2.Date ASC)
FROM Table1 T1
JOIN Table2 T2 ON T1.ID = T2.ID
)
SELECT ID, Date, Desc
FROM ResultCTE
WHERE RowNumber = 1
Method 2: Nested query
;WITH ResultCTE AS
(
SELECT T2.ID, MIN(T2.Date) AS Date
FROM Table1 T1
JOIN Table2 T2 ON T1.ID = T2.ID
GROUP BY T2.ID
)
SELECT T.ID, T.Date, T.Desc
FROM Table2 T
JOIN ResultCTE R
ON R.ID = T.ID AND R.Date = T.Date
SELECT u.firstName,
u.lastName ,
COUNT(*) AS theCount
FROM tbl_appts_change_log c,
tbl_appts a,
tbl_users u
WHERE c.appt_id=a.ID
AND c.user_id =u.userID
AND a.satellite_id = '160'
AND c.date = (SELECT MIN(ci.date)
FROM tbl_appts_change_log ci,
tbl_appts ai
WHERE ci.appt_id = ai.ID
AND ci.appt_id = c.appt_id
AND ai.satellite_id= a.satellite_id
)
GROUP BY u.firstName,
u.lastName
ORDER BY COUNT(*) DESC,
u.firstName,
u.lastName
select u.firstName,u.lastName,count(*) as theCount,cm.MinDate
from (
select c.appt_id,min(c.date) as MinDate
from tbl_appts_change_log c, tbl_appts a
where c.appt_id=a.ID
and a.satellite_id='160'
GROUP BY c.appt_id
) cm
inner join tbl_appts_change_log c on cm.appt_id = c.appt_id and cm.MinDate = c.date
inner join tbl_appts a on c.appt_id=a.ID
inner join tbl_users u on c.user_id=u.userID
group by u.firstName,u.lastName
order by count(*) desc,u.firstName,u.lastName
If what you are looking for is-
Table 1 || Table 2-
ID || ID Date
1 || 1 11/11/2010
1 || 1 10/11/2010
3 || 3 12/01/2010
4 || 4 01/01/2010
4 || 4 02/01/2010
Try using this:
SELECT DISTINCT i1.id, i2.dt
FROM Table1 i1 JOIN (SELECT id, min(date) dt FROM Table2 GROUP BY id) i2
ON i1.id=i2.id
Is this what you're after?
select u.firstName,u.lastName ,count(*) as theCount
from tbl_appts_change_log c,tbl_appts a, tbl_users u
where c.appt_id=a.ID
and c.user_id=u.userID
and a.satellite_id = '160'
and c.date = (
select min(date)
from tbl_appts_change_log c, tbl_appts a
where c.appt_id = a.id
and a.satellite_id = '160'
)
group by u.firstName,u.lastName
order by count(*) desc,u.firstName,u.lastName