How to use cross apply with Sql Kata - sql

I am dont know to construct a query with Cross Apply and SqlKata. I was searching the net and I find out that cross apply was not supported by SqlKata. Is there any other way to achieve my requirements.
var query = new Query("Test as t")
cross apply
(select top 1 t2.TestID from Test as t2 where t1.LegID = t2.LegID order by t2.Sequence desc)
This is the sql query
select * from Test1 t1
cross apply
(select top 1 s.OperationalStopID
from Test2 t2
where t2.LegID = t1.LegID
order by t2.SequenceNumber desc) t3

Just use the Join method and pass "CROSS APPLY" or whatever method you like in the last parameter
check this example on SqlKata Playground
var another = new Query("Test2 as t2")
.WhereColumns("t2.LegID", "=", "t1.LegID")
.Select("s.OperationalStopID")
.OrderByDesc("t2.SequenceNumber")
.Limit(1);
var query = new Query("Test1 as t1").Join(another.As("t3"), j => j, "CROSS APPLY"); // <---

I am not familiar with sqlkata, but you can rewrite your SQL query to an inner join, like:
select DISTINCT
t1.I,
t1.LegID,
x.OperationalStopID
from test1 t1
inner join (select LegID, MAX(OperationalStopID) as OperationalStopID
from test2
group by LegID) x on x.LegID = t1.LegID
I hope you are able to convert this SQL query to sqlkata syntax ?
This query is tested here: DBFIDDLE
P.S.: oops, the DISTINCT should not have been in there anymore, please remove it.

Related

Impala Error : AnalysisException: Multiple subqueries are not supported in expression: (CASE *** WHEN THEN)

I have a where Clause that I need to check if values exists in a table, and I'm doing that in a (subquery). The problem is, that should be made based on
values - 'FIX' and 'VAR'. Depending on each, we need to check on a different table (subquery). To achieve that goal I'm using a Case When statement in the where clause, as shown below:
select *
FROM T1
where
(upper(trim(ITAXAVAR)) = 'S'
and
(
upper(trim(CTIPAMOR)) not in ('A','U','F')
)
)
and
--problem starts here.....
(case ucase(trim(CTIPTXFX)) --Values 'FIX';'VAR';'PUR'
WHEN 'FIX'
THEN
(concat(trim(CPRZTXFX),trim(CTAXAREF)) not in
(select trim(A.tayd91c0_celemtab)
from cd_estruturais.tat91_tabelas A
where A.tayd91c0_ctabela = 'W03' and
--data_date_part = '${Data_ref}' and --por vezes não temos actualização TAT91 para mesma data_ref das tabelas
A.data_date_part = (select max(B.data_date_part)
from cd_estruturais.tat91_tabelas B
where A.tayd91c0_ctabela = B.tayd91c0_ctabela and
B.data_date_part > date_add(TO_DATE(FROM_UNIXTIME(UNIX_TIMESTAMP())),-5)
)
and length(nvl(trim(A.tayd91c0_celemtab),'')) <> 0
)
)
WHEN 'VAR'
THEN
(concat(trim(CTAXAREF),trim(CPERRVTX)) not in
(select concat(trim(A.CTXREF),trim(A.CPERRVTX))
from land_estruturais.cat01_taxref A
where A.data_date_part > date_add(TO_DATE(FROM_UNIXTIME(UNIX_TIMESTAMP())),-5)
and length(nvl(concat(trim(A.CTXREF),trim(A.CPERRVTX)),'')) <> 0
)
)
END
)
;
Below is a simplified view of the same query:
select *
FROM T1
where
(--first criteria
)
and
--problem starts here.....
(case ucase(trim(CTIPTXFX)) --Values 'FIX';'VAR';'PUR'
WHEN 'FIX'
THEN
(field1 not in
(subquery 1)
)
WHEN 'VAR'
THEN
(field1 not in
(subquery 2)
END
)
;
Can anyone tell me what I'm doing wrong, please?
I seems to me that Impala does not support the subqueries inside a Case When Statement.
Thank you.
Impala doesnt support Subqueries in the select list.
So, you need to rewrite the SQL like below -
Use LEFT ANTI JOIN in place of NOT IN() to link subqueries to T1.
To handle case when, use UNION ALL for different conditions.
SELECT * FROM T1
LEFT ANTI JOIN subqry1 y ON T1.id = y.id
WHERE col='FIX'
UNION ALL
SELECT * FROM T1
LEFT ANTI JOIN subqry2 y ON T1.id = y.id
WHERE col='VAR'
I tried to change the simple SQL you posted above. The main SQL is too complex and need table setup and data to prove the logic.
Here is my version of your simple SQL -
select * FROM T1
LEFT ANTI JOIN subquery1 ON subquery1.column = T1.field1
where (--first criteria )
and ucase(trim(CTIPTXFX))='FIX'
UNION ALL
select * FROM T1
LEFT ANTI JOIN subquery2 ON subquery2.column = T1.field1
where (--first criteria )
and ucase(trim(CTIPTXFX))='VAR'
Pls note, Anti join and union all can be expensive so if your table size if huge, please tune them accordingly.

Outer apply to left join conversion

I have a query in SQL Server that I'm trying to migrate to redshift. It has OUTER APPLY in it but Redshift doesn't support it. How can I convert it to left join so that I can use it in Redshift?
....
OUTER APPLY
(
SELECT TOP 1 fel.*
FROM fact.FactEventLog fel
WHERE fpt.ParcelProfileKey = fel.ParcelProfileKey
AND
fpt.LastEventKey = fel.EventLegKey
AND
FPT.DateLastEvent = fel.EventDateTimeUTC
) fel
....
Something answered in this stackoverflow or this answer
Maybe.... someting like...
....
LEFT JOIN
(
SELECT fel.*, row_number() over (partition by ParcelProfileKey, EventLegKey, EventDateTimeUTC order by null) RN
FROM fact.FactEventLog fel
) fel
on fpt.ParcelProfileKey = fel.ParcelProfileKey
AND fpt.LastEventKey = fel.EventLegKey
AND fpt.DateLastEvent = fel.EventDateTimeUTC
AND 1=fel.RN
....
but it just seems so wrong w/o an order by actually defined in the window function. it's like you don't care what random result is returned just so long as 1 exists... but then why not use an exists.... shrug

Check if a combination of fields already exists in the table

My weakest area of SQL are self JOINS, currently struggling with an issue.
I need to find the latest entry in a table, I'm using a WHERE DATEFIELD IN (SELECT MAX(DATEFIELD) FROM TABLE) to do this. I then need to establish if 3 columns from that already exist in the same TABLE.
My latest attempt looks like this -
SELECT * FROM PART_TABLE
WHERE NOT EXISTS
(
SELECT
t1.DATEFIELD
t1.CODE1
t1.CODE2
t1.CODE3
FROM PART_TABLE t1
INNER JOIN PART_TABLE t2 ON t1.UNIQUE = t2.UNQIUE
)
WHERE t1.DATEFIELD IN
(
SELECT MAX(DATEFIELD)
FROM PARTTABLE
)
)
I think part of the issue is that I can't exclude the unique row from t1 when checking in t2 using this method.
Using MSSQL 2014.
The following query will return the latest record from your table and a bit flag whether a duplicate tuple {Code1, Code2, Code3} exists in it under a different identifier:
select top (1) p.*,
case when exists (
select 0 from dbo.Part_Table t where t.Unique != p.Unique
and t.Code1 = p.Code1 and t.Code2 = p.Code2 and t.Code3 = p.Code3
) then 1
else 0 end as [IsDuplicateExists]
from dbo.Part_Table p
order by p.DateField desc;
You can use this example as a template to address your specific needs, which unfortunately aren't immediately apparent from your explanation.

subquery returning more than 1 values

SELECT user_info.s_name, user_info.name, user_info.f_name, user_info.usr_id, user_info.img_path, Village_master.v_nm
FROM Village_master
INNER JOIN User_reg_master ON Village_master.v_id = User_reg_master.v_id
INNER JOIN user_info ON User_reg_master.usr_id = user_info.usr_id
WHERE user_info.usr_id NOT LIKE #u_id
AND user_info.usr_id NOT LIKE (
SELECT pers_dict_master.pers_dict_ids
FROM pers_dict_ids
WHERE pers_dict_master.usr_id=#u_id
)
usr_id| pers_dict_usr_id
1 | 13
1 | 6
The problem you are facing is this ,
user_info.usr_id NOT LIKE
(SELECT pers_dict_master.pers_dict_ids
FROM pers_dict_ids
WHERE pers_dict_master.usr_id=#u_id)
This is your sub query
(SELECT pers_dict_master.pers_dict_ids
FROM pers_dict_ids
WHERE pers_dict_master.usr_id=#u_id)
It is fetching two columns.But In the LIKE command you are using a one Column.
So make it work USE NOT INCOMMAND
SELECT user_info.s_name,
user_info.name,
user_info.f_name,
user_info.usr_id,
user_info.img_path,
Village_master.v_nm
FROM Village_master
INNER JOIN User_reg_master ON Village_master.v_id = User_reg_master.v_id
INNER JOIN user_info ON User_reg_master.usr_id = user_info.usr_id
WHERE user_info.usr_id NOT LIKE #u_id
AND user_info.usr_id NOT IN
( SELECT pers_dict_master.pers_dict_ids
FROM pers_dict_ids
WHERE pers_dict_master.usr_id=#u_id )
You should probably include some more detail about your issue. Is the sub query expected to return more than one result? If so then you could simply use TOP(ie. select top 1 ...) to get just a single result and add an ORDER BY to the sub query if you want to get a certain sorted top value from that result set.
If the issue is that the sub query returns more than 1 result when it shouldn't, then your problem lies deeper. It looks like you may have meant to use IN for the subquery and for a different comparison, but it's difficult to tell. Perhaps you meant this?:
user_info.usr_id NOT IN
(SELECT pers_dict_master.pers_dict_ids
FROM pers_dict_ids WHERE pers_dict_master.usr_id=#u_id)

MS-Access -> SELECT AS + ORDER BY = error

I'm trying to make a query to retrieve the region which got the most sales for sweet products. 'grupo_produto' is the product type, and 'regiao' is the region. So I got this query:
SELECT TOP 1 r.nm_regiao, (SELECT COUNT(*)
FROM Dw_Empresa
WHERE grupo_produto='1' AND
cod_regiao = d.cod_regiao) as total
FROM Dw_Empresa d
INNER JOIN tb_regiao r ON r.cod_regiao = d.cod_regiao ORDER BY total DESC
Then when i run the query, MS-Access asks for the "total" parameter. Why it doesn't consider the newly created 'column' I made in the select clause?
Thanks in advance!
Old Question I know, but it may help someone knowing than while you cant order by aliases, you can order by column index. For example, this will work without error :
SELECT
firstColumn,
IIF(secondColumn = '', thirdColumn, secondColumn) As yourAlias
FROM
yourTable
ORDER BY
2 ASC
The results would then be ordered by the values found in the second column wich is the Alias "yourAlias".
Aliases are only usable in the query output. You can't use them in other parts of the query. Unfortunately, you'll have to copy and paste the entire subquery to make it work.
You can do it like this
select * from(
select a + b as c, * from table)
order by c
Access has some differences compared to Sql Server.
Why it doesn't consider the newly
created 'column' I made in the select
clause?
Because Access (ACE/Jet) is not compliant with the SQL-92 Standard.
Consider this example, which is valid SQL-92:
SELECT a AS x, c - b AS y
FROM MyTable
ORDER
BY x, y;
In fact, x and y the only valid elements in the ORDER BY clause because all others are out of scope (ordinal numbers of columns in the SELECT clause are valid though their use id deprecated).
However, Access chokes on the above syntax. The equivalent Access syntax is this:
SELECT a AS x, c - b AS y
FROM MyTable
ORDER
BY a, c - b;
However, I understand from #Remou's comments that a subquery in the ORDER BY clause is invalid in Access.
Try using a subquery and order the results in an outer query.
SELECT TOP 1 * FROM
(
SELECT
r.nm_regiao,
(SELECT COUNT(*)
FROM Dw_Empresa
WHERE grupo_produto='1' AND cod_regiao = d.cod_regiao) as total
FROM Dw_Empresa d
INNER JOIN tb_regiao r ON r.cod_regiao = d.cod_regiao
) T1
ORDER BY total DESC
(Not tested.)
How about:
SELECT TOP 1 r.nm_regiao
FROM (SELECT Dw_Empresa.cod_regiao,
Count(Dw_Empresa.cod_regiao) AS CountOfcod_regiao
FROM Dw_Empresa
WHERE Dw_Empresa.[grupo_produto]='1'
GROUP BY Dw_Empresa.cod_regiao
ORDER BY Count(Dw_Empresa.cod_regiao) DESC) d
INNER JOIN tb_regiao AS r
ON d.cod_regiao = r.cod_regiao
I suggest using an intermediate query.
SELECT r.nm_regiao, d.grupo_produto, COUNT(*) AS total
FROM Dw_Empresa d INNER JOIN tb_regiao r ON r.cod_regiao = d.cod_regiao
GROUP BY r.nm_regiao, d.grupo_produto;
If you call that GroupTotalsByRegion, you can then do:
SELECT TOP 1 nm_regiao, total FROM GroupTotalsByRegion
WHERE grupo_produto = '1' ORDER BY total DESC
You may think it's extra work to create the intermediate query (and, in a sense, it is), but you will also find that many of your other queries will be based off of GroupTotalsByRegion. You want to avoid repeating that logic in many other queries. By keeping it in one view, you provide a simplified route to answering many other questions.
How about use:
WITH xx AS
(
SELECT TOP 1 r.nm_regiao, (SELECT COUNT(*)
FROM Dw_Empresa
WHERE grupo_produto='1' AND
cod_regiao = d.cod_regiao) as total
FROM Dw_Empresa d
INNER JOIN tb_regiao r ON r.cod_regiao = d.cod_regiao
) SELECT * FROM xx ORDER BY total