SQL Inner join group... missing expression - sql

I have following query, which works fine:
SELECT c.id, c.customer_name, b.batch_prefix, b.BatchCount, b.InvoiceCount, e.time_of_delivery, e.time_of_delivery_mail, e.time_of_delivery_clock
FROM koll_customers c
INNER JOIN (
SELECT batch_prefix, COUNT(*) AS BatchCount,
SUM (batch_counter) AS InvoiceCount
FROM koll_batchlogs
WHERE
exists_db = 0
and is_checked = 1
and batch_counter > 0
and trunc(created_date) > trunc(sysdate-7)
GROUP BY batch_prefix) b
ON b.batch_prefix=c.customer_prefix
INNER JOIN (
SELECT id, time_of_delivery, time_of_delivery_mail, time_of_delivery_clock
FROM koll_customer_export) e
ON e.id = c.id
My requirement is to add another column 'YellowCategory'. For that I tried to change the query to following:
SELECT c.id, c.customer_name, b.batch_prefix, b.BatchCount, b.InvoiceCount, e.time_of_delivery, e.time_of_delivery_mail, e.time_of_delivery_clock, e.YellowCategory
FROM koll_customers c
INNER JOIN (
SELECT batch_prefix, COUNT(*) AS BatchCount,
SUM (batch_counter) AS InvoiceCount
FROM koll_batchlogs
WHERE
exists_db = 0
and is_checked = 1
and batch_counter > 0
and trunc(created_date) > trunc(sysdate-7)
GROUP BY batch_prefix) b
ON b.batch_prefix=c.customer_prefix
INNER JOIN (
SELECT id, time_of_delivery, time_of_delivery_mail, time_of_delivery_clock, COUNT(b.batch_counter) AS YellowCategory,
FROM koll_customer_export
WHERE to_date(created_date,'DD.MM.RRRR HH24:MI:SS') < to_date(sysdate-time_of_delivery,'DD.MM.RRRR HH24:MI:SS')
GROUP BY b.batch_counter) e
ON e.id = c.id
But then I get "missing expression" error. I guess in last INNER JOIN. Don't know where is the problem... Any help?
Update
With following query, I get b.batch_counter invalid identifier error now.
SELECT c.id, c.customer_name, b.batch_prefix, b.BatchCount,
b.InvoiceCount, e.time_of_delivery, e.time_of_delivery_mail,
e.time_of_delivery_clock, e.YellowCategory
FROM koll_customers c
INNER JOIN (
SELECT batch_prefix, batch_counter, COUNT(*) AS BatchCount,
SUM (batch_counter) AS InvoiceCount
FROM koll_batchlogs
WHERE exists_db = 0 and is_checked = 1
and batch_counter > 0 and trunc(created_date) > trunc(sysdate-7)
GROUP BY batch_prefix
) b
ON b.batch_prefix=c.customer_prefix
INNER JOIN (
SELECT id, time_of_delivery, time_of_delivery_mail,
time_of_delivery_clock,
COUNT(b.batch_counter) AS YellowCategory
FROM koll_customer_export
WHERE to_date(created_date,'DD.MM.RRRR HH24:MI:SS')
< to_date(sysdate- time_of_delivery,'DD.MM.RRRR HH24:MI:SS')
GROUP BY b.batch_counter
) e
ON e.id = c.id

Is this the query you want?
SELECT c.id, c.customer_name, b.batch_prefix, b.BatchCount, b.InvoiceCount,
e.time_of_delivery, e.time_of_delivery_mail, e.time_of_delivery_clock, e.YellowCategory
FROM koll_customers c INNER JOIN
(SELECT batch_prefix, COUNT(*) AS BatchCount, SUM (batch_counter) AS InvoiceCount
FROM koll_batchlogs
WHERE exists_db = 0 and is_checked = 1 and batch_counter > 0 and
trunc(created_date) > trunc(sysdate-7)
GROUP BY batch_prefix
) b
ON b.batch_prefix = c.customer_prefix INNER JOIN
(SELECT id, time_of_delivery, time_of_delivery_mail, time_of_delivery_clock,
COUNT(*) AS YellowCategory,
FROM koll_customer_export
WHERE to_date(created_date, 'DD.MM.RRRR HH24:MI:SS') < to_date(sysdate-time_of_delivery,'DD.MM.RRRR HH24:MI:SS')
GROUP BY id, time_of_delivery, time_of_delivery_mail, time_of_delivery_clock
) e
ON e.id = c.id;
It is impossible for me to say if this is what you really need. But I think the query will at least compile so you can run it.. The where clause in the e subquery looks really strange. Why would you be converting a date column into a date column using to_date()?

You typed one comma too much at the end of the SELECT list inside the last INNER JOIN.

Related

Pull a separate column that matches the (min) of an aggregate function

It works well so far but I am stumped from here as I am brand new to this. This query finds the closest distance match, pairing up every item in the "FAILED" folder against everything that isn't in the "FAILED" folder.
There is a column "RouteID" in the "table p" that I want to match up with the min() aggregate.
I cannot process how to make the SELECT query simply show the associated "RouteID" column from tbl p but ultimately, I want to turn this into an update query that will SET a.Route = p.Route that is associated with the min()
Any help would be appreciated.
SELECT a.name, a.Reference1,
MIN(round(ACOS(COS(RADIANS(90-a.lat))
*COS(RADIANS(90-p.latpoint))
+SIN(RADIANS(90-a.lat))
*SIN(RADIANS(90-p.latpoint))
*COS(RADIANS(a.lon-p.longpoint)))
*3958.756,2)) AS 'DISTANCE'
FROM tblOrder AS a WITH (NOLOCK)
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrder b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS p ON 1=1
WHERE a.CustID = 180016
AND a.RouteID = 'FAILED'
AND a.StopType = 1
AND P.RouteID <> 'FAILED'
GROUP BY
a.name, a.Reference1
You can select them separately and then join them
SELECT c.name, c.Reference1, q.RouteID
FROM
(
SELECT a.name, a.Reference1,
MIN(round(ACOS(COS(RADIANS(90-a.lat))
*COS(RADIANS(90-p.latpoint))
+SIN(RADIANS(90-a.lat))
*SIN(RADIANS(90-p.latpoint))
*COS(RADIANS(a.lon-p.longpoint)))
*3958.756,2)) AS 'DISTANCE'
FROM tblOrder AS a WITH (NOLOCK)
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrder b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS p ON 1=1
WHERE a.CustID = 180016
AND a.RouteID = 'FAILED'
AND a.StopType = 1
AND P.RouteID <> 'FAILED'
GROUP BY
a.name, a.Reference1
) c
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrderRouteStops b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS q
ON q.routeID = c.DISTANCE

UNION on 2 joined queries

I have 2 working queries that are joined by subselects using WITH in DB2.
They each work separately but I can't seem to find the best way to properly combine or union them.
The first query:
with c as(
select
employee,
sum(salesPrice) as priorSpecifics
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2018-01-01' and '2018-01-31'
and g.details = 'CategoryOne'
group by employee
), d as(
select
employee,
sum(salesPrice) as priorTotals
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2018-01-01' and '2018-01-31'
group by employee
)
Select ifnull(c.employee,d.employee) as employee
,c.priorSpecifics
,d.priorTotals
,cast(Round((DEC(c.priorSpecifics,12,2)/DEC(d.priorTotals,12,2)) * 100,2) as decimal(12,2)) as priorPercent
from c full join d ON (c.employee = d.employee);
Returns 4 columns
and the 2nd query
with c as(
select
employee,
sum(salesPrice) as currentSpecifics
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2019-01-01' and '2019-01-31'
and g.details = 'CategoryOne'
group by employee
), d as(
select
employee,
sum(salesPrice) as currentTotals
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2019-01-01' and '2019-01-31'
group by employee
)
Select ifnull(c.employee,d.employee) as employee
,c.currentSpecifics
,d.currentTotals
,cast(Round((DEC(c.currentSpecifics,12,2)/DEC(d.currentTotals,12,2)) * 100,2) as decimal(12,2)) as currentPercent
from c full join d ON (c.employee = d.employee);
Returns 4 as well. The field employee is the only thing that is shared between all.
How can I combine this into one query to get one employee column and then all of my sum/percent columns following?
I think you can do everything you want with conditional aggregation:
select employee,
sum(case when d.newDate between '2018-01-01' and '2018-01-31' and g.details = 'CategoryOne' then salesPrice end) as priorSpecifics,
sum(case when d.newDate between '2019-01-01' and '2019-01-31' and g.details = 'CategoryOne' then salesPrice end) as currentSpecifics,
sum(case when d.newDate between '2018-01-01' and '2018-01-31' then salesPrice end) as priorTotals,
sum(case when d.newDate between '2019-01-01' and '2019-01-31' then salesPrice end) as currentTotals
from schema1.orders g inner join
dateSchema.dates d
on g.dateField = d.dateField
group by employee;
I'll let you fill in with the additional calculations.
If all the above queries are working then you already have everything you need.
You must combine from the 1st group, the first 2 to make the prior query, then
from the 2nd group to make the cur query
and finally join the prior query to the cur query:
with
c as(
select
employee,
sum(salesPrice) as priorSpecifics
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2018-01-01' and '2018-01-31'
and g.details = 'CategoryOne'
group by employee
),
d as(
select
employee,
sum(salesPrice) as priorTotals
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2018-01-01' and '2018-01-31'
group by employee
),
prior as (
Select ifnull(c.employee,d.employee) as employee
,c.priorSpecifics
,d.priorTotals
,cast(Round((DEC(c.priorSpecifics,12,2)/DEC(d.priorTotals,12,2)) * 100,2) as decimal(12,2)) as priorPercent
from c full join d ON (c.employee = d.employee)
),
e as(
select
employee,
sum(salesPrice) as currentSpecifics
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2019-01-01' and '2019-01-31'
and g.details = 'CategoryOne'
group by employee
),
f as(
select
employee,
sum(salesPrice) as currentTotals
from schema1.orders g
inner join dateSchema.dates d
on g.dateField = d.dateField
where d.newDate between '2019-01-01' and '2019-01-31'
group by employee
),
cur as (
Select ifnull(e.employee,f.employee) as employee
,e.currentSpecifics
,f.currentTotals
,cast(Round((DEC(e.currentSpecifics,12,2)/DEC(f.currentTotals,12,2)) * 100,2) as decimal(12,2)) as currentPercent
from e full join f ON (e.employee = f.employee)
)
Select ifnull(p.employee, c.employee) as employee
,p.priorSpecifics
,p.priorTotals
,p.priorPercent
,c.currentSpecifics
,c.currentTotals
,c.currentPercent
from prior p full join cur c ON (c.employee = c.employee);

Oracle SQL inner join

I have following query, which works fine.
SELECT c.id, c.customer_name, b.batch_prefix, b.BatchCount, b.InvoiceCount, e.time_of_delivery, e.time_of_delivery_mail, e.time_of_delivery_clock
FROM koll_customers c
INNER JOIN (
SELECT batch_prefix, COUNT(*) AS BatchCount,
SUM (batch_counter) AS InvoiceCount
FROM koll_batchlogs
WHERE
exists_db = 0
and is_checked = 1
and batch_counter > 0
and trunc(created_date) > trunc(sysdate-7)
GROUP BY batch_prefix) b
ON b.batch_prefix=c.customer_prefix
INNER JOIN koll_customer_export e
ON c.id = e.id
But, when I add another JOIN (last join) with SELECT and WHERE it gives error: "Invalid identifier"
SELECT c.id, c.customer_name, b.batch_prefix, b.BatchCount, b.InvoiceCount
FROM koll_customers c
INNER JOIN (
SELECT batch_prefix, COUNT(*) AS BatchCount,
SUM (batch_counter) AS InvoiceCount
FROM koll_batchlogs
WHERE
exists_db = 0
and is_checked = 1
and batch_counter > 0
and trunc(created_date) > trunc(sysdate-7)
GROUP BY batch_prefix) b
ON b.batch_prefix=c.customer_prefix
INNER JOIN (
SELECT time_of_delivery
FROM koll_customer_export
WHERE time_of_delivery=2) e
ON e.id = c.id
I wonder, what is problem with the last join?
This is the join:
INNER JOIN
(SELECT time_of_delivery
FROM koll_customer_export
WHERE time_of_delivery=2
) e
ON e.id = c.id
You are referring to e.id, but you don't have that in the subquery. Try this:
INNER JOIN
(SELECT time_of_delivery, id
--------------------------^
FROM koll_customer_export
WHERE time_of_delivery=2
) e
ON e.id = c.id
INNER JOIN (
SELECT time_of_delivery
FROM koll_customer_export
WHERE time_of_delivery=2) e
ON e.id = c.id
there is no column named id.

SQL join two simple query with count and groupby

hello i have 2 queries and i wanna join together but i don't know how...
SELECT *, count(*) as invii
FROM professionisti JOIN preventivi_invii ON
professionisti.email=preventivi_invii.email
GROUP BY professionisti.email
HAVING invii> 300
SELECT *, count(*) as acquisti
FROM professionisti JOIN contatti_acquistati ON
professionisti.email=contatti_acquistati.email
GROUP BY professionisti.email
HAVING acquisti> 5
the problem for me is multiple count and the group by with same column.
thank u
How about the below query. You would just change the WHERE clause to meet your needs.
SQL Fiddle Example:
SELECT * FROM
(
SELECT p.email,
CASE WHEN ISNULL(m1.invii) THEN 0 ELSE m1.invii END AS invii,
CASE WHEN ISNULL(m2.acquisti) THEN 0 ELSE m2.acquisti END AS acquisti
FROM professionisti p
LEFT JOIN
(
SELECT pp.email, COUNT(*) AS invii
FROM preventivi_invii pp
GROUP BY pp.email
) AS m1 ON p.email = m1.email
LEFT JOIN
(
SELECT c.email, COUNT(*) AS acquisti
FROM contatti_acquistati c
GROUP BY c.email
) AS m2 ON p.email = m2.email
) AS mm
WHERE mm.invii = 0
OR mm.acquisti = 0;
Or you could use:
SELECT * FROM
(
SELECT p.email,
(
SELECT
CASE WHEN ISNULL(COUNT(*)) THEN 0 ELSE COUNT(*) END
FROM preventivi_invii pp
WHERE pp.email = p.email
) AS invii,
(
SELECT
CASE WHEN ISNULL(COUNT(*)) THEN 0 ELSE COUNT(*) END
FROM contatti_acquistati c
WHERE c.email = p.email
) AS acquisti
FROM professionisti p
) AS mm
WHERE mm.invii = 0
OR mm.acquisti = 0

How to insert into one table from multiple table while using UNION

I have the following query which queries different table and uses the UNION operator to display a set of data:
-----TOTAL COUNT OF ACTIVE DEA----- DEA
select attr1671 as 'TYPE', count(attr1668) as 'TOTAL'
from [MyServer].[DBOTYPE].instance.rmobjectinsta d inner join (select fk1665, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobjectinsta
group by fk1665) n on d.objectid = n.newobjectid where attr1671 = 'DEA' and cast(attr1668 as date) > cast(getdate()+30 as date) and activestatus = 0
group by attr1671
-----TOTAL COUNT OF ACTIVE LICENSES----- LICENSE
UNION
select 'LICENSE' as 'TYPE', count(*) as 'TOTAL'
from [MyServer].[DBOTYPE].instance.rmobjectin t inner join (select fk1656, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobjectin
group by fk1656) c on t.objectid = c.newobjectid where cast(attr1660 as date) > cast(getdate()+30 as date) and activestatus = 0
-----TOTAL INFECTION CERTIFICATIONS ACTIVE----- INFECTION
UNION
select 'INFECTION' as 'TYPE', count(*) 'TOTAL'
from [MyServer].[DBOTYPE].instance.rmobject z inner join (select fk1676, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobject
group by fk1676) h on z.objectid = h.newobjectid where cast(attr1680 as date) > cast(getdate()+30 as date) and activestatus = 0
-----TOTAL COUNT OF ACTIVE CDS----- CDS
UNION
select attr1671 as 'TYPE', count(attr1668) as 'TOTAL'
from [MyServer].[DBOTYPE].instance.rmobje k inner join (select fk1665, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobje
group by fk1665) l on k.objectid = l.newobjectid where attr1671 = 'CDS' and cast(attr1668 as date) > cast(getdate()+30 as date) and activestatus = 0
group by attr1671
Which displays the following:
TYPE TOTAL
CDS 45
DEA 56
INFECTION 67
LICENSE 41
I would like to insert the data into a table that I can import as a DataSet in my SSRS report. How can I achieve it?
I tried doing the following:
-----TOTAL COUNT OF ACTIVE DEA----- DEA
select attr1671 as 'TYPE', count(attr1668) as 'TOTAL'
INTO [MYDB].[DBO].[myT] --on first run and then comment
from [MyServer].[DBOTYPE].instance.rmobjectinsta d inner join (select fk1665, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobjectinsta
group by fk1665) n on d.objectid = n.newobjectid where attr1671 = 'DEA' and cast(attr1668 as date) > cast(getdate()+30 as date) and activestatus = 0
group by attr1671
-----TOTAL COUNT OF ACTIVE LICENSES----- LICENSE
UNION
select 'LICENSE' as 'TYPE', count(*) as 'TOTAL'
INTO [MYDB].[DBO].[myT] --on first run and then comment
from [MyServer].[DBOTYPE].instance.rmobjectin t inner join (select fk1656, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobjectin
group by fk1656) c on t.objectid = c.newobjectid where cast(attr1660 as date) > cast(getdate()+30 as date) and activestatus = 0
-----TOTAL INFECTION CERTIFICATIONS ACTIVE----- INFECTION
UNION
select 'INFECTION' as 'TYPE', count(*) 'TOTAL'
INTO [MYDB].[DBO].[myT] --on first run and then comment
from [MyServer].[DBOTYPE].instance.rmobject z inner join (select fk1676, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobject
group by fk1676) h on z.objectid = h.newobjectid where cast(attr1680 as date) > cast(getdate()+30 as date) and activestatus = 0
-----TOTAL COUNT OF ACTIVE CDS----- CDS
UNION
select attr1671 as 'TYPE', count(attr1668) as 'TOTAL'
INTO [MYDB].[DBO].[myT] --on first run and then comment
from [MyServer].[DBOTYPE].instance.rmobje k inner join (select fk1665, max(objectid) 'newobjectid'
from [MyServer].[DBOTYPE].instance.rmobje
group by fk1665) l on k.objectid = l.newobjectid where attr1671 = 'CDS' and cast(attr1668 as date) > cast(getdate()+30 as date) and activestatus = 0
group by attr1671
But that didn't work. Please help...
This is the error I get:
Msg 196, Level 15, State 1, Line 2
SELECT INTO must be the first query in a statement containing a UNION, INTERSECT or EXCEPT operator.
You can try wrapping the whole thing as a subselect:
select *
into <whatever>
from (<your query here>
) t;
Try this :
With Emp_CTE (Employee,Count)
AS
(
Select Firstname as Employee , Count(*) as Count from Employee
where FirstName like 'V%'
group by FirstName
union
Select Firstname as Employee , Count(*) as Count from Employee
where FirstName like 'M%'
group by FirstName
)
Select * into dbo.EmployeeCount from Emp_CTE;