How can I eliminate the subquery from this sql query? - sql

I have a query which should work, but it seems I am a victim of a poor database technology. I need to run the query below on a Pervasive SQL database. The manufacturer of the product using Pervasive tells me the version they are using is 10 which should support subqueries, but I have yet to be able to run even a simple subquery. So, I am wondering if the following query can be rewritten to eliminate the subquery:
SELECT
OuterTime.Employee,
OuterTime.Date,
OuterTime.Pay_ID,
OuterTime.Description,
OuterTime.Equipment,
OuterTime.JC_Cost_Code,
OuterTime.JC_Category,
OuterTime.Units,
(
SELECT
SUM(SubQueryTime.Units)
FROM
PRT_NEW__TIME AS SubQueryTime
WHERE
SubQueryTime.Employee = OuterTime.Employee
GROUP BY
SubQueryTime.Employee
) AS TotalHoursForEmp
FROM
PRT_NEW__TIME AS OuterTime

In standard SQL you can do this, though I have no idea about PervasiveSQL specifically...
SELECT
OuterTime.Employee,
OuterTime.Date,
OuterTime.Pay_ID,
OuterTime.Description,
OuterTime.Equipment,
OuterTime.JC_Cost_Code,
OuterTime.JC_Category,
OuterTime.Units,
COALESCE(TotalHoursForEmp.TotalUnits, 0) AS TotalUnits
FROM
PRT_NEW__TIME AS OuterTime
LEFT JOIN
(
SELECT
Employee,
SUM(Units) AS TotalUnits
FROM
PRT_NEW__TIME
GROUP BY
Employee
)
AS TotalHoursForEmp
ON TotalHoursForEmp.Employee = OuterTime.Employee

Not a Pervasive SQL guy, but would this work? Not sure it accomplishes your query goals:
SELECT
OuterTime.Employee,
OuterTime.Date,
OuterTime.Pay_ID,
OuterTime.Description,
OuterTime.Equipment,
OuterTime.JC_Cost_Code,
OuterTime.JC_Category,
SUM(OuterTime.Units) AS TotalHoursForEmp
GROUP BY OuterTime.Employee, OuterTime.Date, OuterTime.Pay_ID,
OuterTime.Description, OuterTime.Equipment, OuterTime.JC_Cost_Code,
OuterTime.JC_Category
FROM
PRT_NEW__TIME AS OuterTime

Related

SQL Server query (MAX+COUNT)

I am currently working on a quick query on Microsoft SQL Server that should return different INSTALLATION that had the MAX amount of EVENTS on the last year.
This is what I got so far but I know that this is not the right way and was hoping for some insight:
SELECT
i.idInstalac, i.nomInstalac, COUNT(e.idEvento) as cantEventos
FROM
Instalacion i, Eventos e
WHERE
i.idInstalac = e.idInstalac
AND YEAR(e.fchEvento) = 2019
GROUP BY
i.idInstalac, i.nomInstalac
HAVING
MAX cantEventos
Thanks
A simple solution is TOP (1) WITH TIES:
SELECT TOP (1) WITH TIES i.idInstalac, i.nomInstalac, COUNT(e.idEvento) as cantEventos
FROM Instalacion i
INNER JOIN Eventos e ON i.idInstalac = e.idInstalac
WHERE e.fchEvento >= '2019-01-01' and e.fchEvento < '2020-01-01'
GROUP BY i.idInstalac,i.nomInstalac
ORDER BY cantEventos DESC
Note that I rewrote your implicit JOIN as an explicit, modern join (with the ON keyword): implicit join is an old syntax that should not be used in new code. I also changed the date filter in the WHERE clause: using date functions on the column is less efficient, and prevents the database from using an existing index

Migrate query with START WITH and CONNECT BY PRIOR from oracle to postgresql

I am migrating a process from oracle to postgresql, and I am in another problem with the conversion of them.
I have been researching how to migrate an oracle query, which has "START WITH" and "CONNECT BY PRIOR", I have documented with respect to this, and I think the easiest way to do it is with "WITH RECURSIVE"
Make the migration of the query, but I'm not sure about the results they throw since the bd oracle and postgres are different, and it is not possible to homologate the bd.
This is the query in Oracle
SELECT edef_codigo, etdf_transac, edef_detail--, LEVEL
FROM edeft
WHERE edef_distrib in('OM', 'N/A')
AND pers_codigo_socadm = 311745439
AND ctac_correlativo = 7513
START WITH etdf_transac = 'SDN'
CONNECT BY PRIOR edef_codigo = edef_padre;
And this is the query in postgresql
WITH RECURSIVE edf AS ( SELECT ed.edef_codigo, ed.etdf_transac,
ed.edef_detail
FROM edeft ed
WHERE ed.edef_distrib in('OM', 'N/A')
AND ed.pers_codigo_socadm = 311745439
AND ed.ctac_correlativo = 7513
AND ed.etdf_transac = 'SDN'
UNION ALL
SELECT ed.edef_codigo, ed.etdf_transac,
ed.edef_detail
FROM edeft ed
JOIN edf ON edf.edef_codigo = ed.edef_padre
WHERE ed.edef_distrib in('OM', 'N/A')
AND ed.pers_codigo_socadm = 311745439
AND ed.ctac_correlativo = 7513
)
SELECT * FROM edf;
I am still new to postgres and this consultation has made me especially complicated, since I have not found examples similar to what I have.
Yes, I have also used "Connect by prior" conversion in Postgresql using "With Recursive" queries And I find this is the right approach.
One simple example in reference to connect by prior:
Oracle:
Select name, age from user_test connect by prior user_id=parent_id start with user_id='a';
Postgres:
with recursive cte_name as
(select u1.name, u1.user_id, u1.age from user_test u1 where user_id='a'
UNION ALL select u2.name, u2.user_id, u2.age from user_test u2
join cte_name on cte_name.user_id=u2.parent_id) select name,age from cte_name;

Order of Joins SQL Server

I ran across a curious issue earlier today while writing a multiple JOIN query in MS SQL Server and I am hoping somebody may be able to help me to understand better. Typically I like to join tables in the order I pull from them in the SELECT statement (just seems easier and cleaner to me). The below statement works only because it is not in order of the SELECT statement and I don't know why. If I re-wrote it to join VW_ORDER_HEADER --> VW_ORDER_ITEM --> VW_PO_ITEM in that order it returns no results. I only discovered this works after designing it in Access and looking at the resulting SQL. I am not new to SQL Server but at first and second glance I can't see why the order of the join would make a difference... Thanks in advance
SELECT O.SALES_ORDER_NUMBER,
O.BILL_TO,
O.SHIP_TO,
O.SOLD_TO,
O.ORDER_DATE,
O.REQUESTED_DELIVERY_DATE,
O.VALID_TO_DATE,
O.OPEN_QUANTITY,
OI.MATERIAL,
PI.PO_NUMBER
FROM VW_PO_ITEM PI
JOIN VW_ORDER_ITEM OI ON PI.MATERIAL = OI.MATERIAL
JOIN VW_ORDER_HEADER O ON OI.SALES_ORDER_NUMBER = O.SALES_ORDER_NUMBER
WHERE OI.MATERIAL = 'BA7948'
AND O.OPEN_QUANTITY > 0
AND O.VALID_TO_DATE >= GETDATE()
ORDER BY O.SALES_ORDER_NUMBER,
O.ORDER_DATE ASC;

How to combine this query

In the query
cr is customers,
chh? ise customer_pays,
cari_kod is customer code,
cari_unvan1 is customer name
cha_tarihi is date of pay,
cha_meblag is pay amount
The purpose of query, the get the specisified list of customers and their last date for pay and amount of money...
Actually my manager needs more details but the query is very slow and that is why im using only 3 subquery.
The question is how to combine them ?
I have researched about Cte and "with clause" and "subquery in "where " but without luck.
Can anybody have a proposal.
Operating system is win2003 and sql server version is mssql 2005.
Regards
select cr.cari_kod,cr.cari_unvan1, cr.cari_temsilci_kodu,
(select top 1
chh1.cha_tarihi
from dbo.CARI_HESAP_HAREKETLERI chh1 where chh1.cha_kod=cr.cari_kod order by chh1.cha_RECno) as sontar,
(select top 1
chh2.cha_meblag
from dbo.CARI_HESAP_HAREKETLERI chh2 where chh2.cha_kod=cr.cari_kod order by chh2.cha_RECno) as sontutar
from dbo.CARI_HESAPLAR cr
where (select top 1
chh3.cha_tarihi
from dbo.CARI_HESAP_HAREKETLERI chh3 where chh3.cha_kod=cr.cari_kod order by chh3.cha_RECno) >'20130314'
and
cr.cari_bolge_kodu='322'
or
cr.cari_bolge_kodu='324'
order by cr.cari_kod
You will probably speed up the query by changing your last where clause to:
where (select top 1 chh3.cha_tarihi
from dbo.CARI_HESAP_HAREKETLERI chh3 where chh3.cha_kod=cr.cari_kod
order by chh3.cha_RECno
) >'20130314' and
cr.cari_bolge_kodu in ('322', '324')
order by cr.cari_kod
Assuming that you want both the date condition met and one of the two codes. Your original logic is the (date and code = 322) OR (code = 324).
The overall query can be improved by finding the record in the chh table and then just using that. For this, you want to use the window function row_number(). I think this is the query that you want:
select cari_kod, cari_unvan1, cari_temsilci_kodu,
cha_tarihi, cha_meblag
from (select cr.*, chh.*,
ROW_NUMBER() over (partition by chh.cha_kod order by chh.cha_recno) as seqnum
from dbo.CARI_HESAPLAR cr join
dbo.CARI_HESAP_HAREKETLERI chh
on chh.cha_kod=cr.cari_kod
where cr.cari_bolge_kodu in ('322', '324')
) t
where chh3.cha_tarihi > '20130314' and seqnum = 1
order by cr.cari_kod;
This version assumes the revised logic date/code logic.
The inner subquery select might generate an error if there are two columns with the same name in both tables. If so, then just list the columns instead of using *.

SQL Group By question SQL Server 2005 CE

I'm having a problem with an sql query that i use for my mobile application which uses sql server 2005 ce. I'm not so good with t-sql, so have a problem with this query
SELECT TP.ID_TASK_MASTER, TP.ID_PROBLEM, TP.ID_TASK_PROBLE, P.DS_PROBLEM,
TP.SW_HASOK, TP.SW_HASNOK, TP.SW_HASTOK, TP.SW_HASVALUE,
TP.NO_VALUE1, TP.NO_VALUE2
FROM TASK_PROBLEMS TP
INNER JOIN PROBLEMS P
ON TP.ID_PROBLEM = P.ID_PROBLEM
GROUP BY P.DS_PROBLEM,TP.ID_TASK_MASTER, TP.ID_PROBLEM, TP.ID_TASK_PROBLE
HAVING TP.ID_TASK_MASTER = #P_IDTASKMASTER
What i try to do is doing a group by on ds_problem field, getting an error like this :
{"In aggregate and grouping expressions, the SELECT clause can contain only aggregates and grouping expressions. [ Select clause = TP,SW_HASOK ]"}
So what i made wrong? Thanks..
I suppose what you meant to do was
SELECT TP.ID_TASK_MASTER, TP.ID_PROBLEM, TP.ID_TASK_PROBLE, P.DS_PROBLEM,
TP.SW_HASOK, TP.SW_HASNOK, TP.SW_HASTOK, TP.SW_HASVALUE,
TP.NO_VALUE1, TP.NO_VALUE2
FROM TASK_PROBLEMS TP
INNER JOIN PROBLEMS P
ON TP.ID_PROBLEM = P.ID_PROBLEM
WHERE TP.ID_TASK_MASTER = #P_IDTASKMASTER
ORDER BY P.DS_PROBLEM,TP.ID_TASK_MASTER, TP.ID_PROBLEM,TP.ID_TASK_PROBLE