Can I write sub query in KSQL? - apache-kafka

I am new to ksql and have been using mysql for the longest time.
I would like to know is there anyway to have subqueries in KSQL?
This query works without any problem :
SELECT a.executedate, count(a.pno), sum(a.amount) FROM
tb3_withdraw_record_summary a WHERE a.status='3' GROUP BY
a.executedate;
Whereas this query returns an error message:
SELECT a.executedate, count(a.pno), sum(a.amount), (SELECT COUNT(b.pno)
FROM tb3_withdraw_record_summary b WHERE b.status='5' AND
b.executedate = a.executedate) FROM tb3_withdraw_record_summary a
WHERE a.status='3' GROUP BY a.executedate
'Failed to prepare statement: 'B' is not a valid stream/table name or alias.
Caused by: 'B' is not a valid stream/table name or alias.'
Anyway for me to make this work? Thanks!

nested query feature is not currently supported by Ksql but you can do it in following way -
1) CREATE STREAM B AS SELECT COUNT(b.pno)
FROM tb3_withdraw_record_summary b WHERE b.status='5';
2) SELECT a.executedate, count(a.pno), sum(a.amount) FROM tb3_withdraw_record_summary a JOIN B within 5 hours ON b.executedate = a.executedate WHERE a.status='3' GROUP BY a.executedate
Keep in mind that join is very different meaning then relational database world, here data is being partitioned through keys in multiple buckets and it conceptually a "colocated" join. more details about time-window here.
Hope it will help.

SubQuery functionality is not implemented for KSQL.
https://github.com/confluentinc/ksql/issues/745

I am not familiar with KSQL, but perhaps this does what you want:
SELECT wrs.executedate,
SUM(CASE WHEN wrs.status IN ('3') THEN 1 ELSE 0 END),
SUM(CASE WHEN wrs.status IN ('3') THEN amount ELSE 0 END),
SUM(CASE WHEN wrs.status IN ('5') THEN 1 ELSE 0 END)
FROM tb3_withdraw_record_summary wrs
WHERE wrs.status IN ('3', '5')
GROUP BY wrs.executedate;

Related

How to keep one record in specific column and make other record value 0 in group by clause in PostgreSQL?

I have a set of data like this
The Result should look Like this
My Query
SELECT max(pi.pi_serial) AS proforma_invoice_id,
max(mo.manufacturing_order_master_id) AS manufacturing_order_master_id,
max(pi.amount_in_local_currency) AS sales_value,
FROM proforma_invoice pi
JOIN schema_order_map som ON pi.pi_serial = som.pi_id
LEFT JOIN manufacturing_order_master mo ON som.mo_id = mo.manufacturing_order_master_id
WHERE to_date(pi.proforma_invoice_date, 'DD/MM/YYYY') BETWEEN to_date('01/03/2021', 'DD/MM/YYYY') AND to_date('19/04/2021', 'DD/MM/YYYY')
AND pi.pi_serial in (9221,
9299)
GROUP BY mo.manufacturing_order_master_id,
pi.pi_serial
ORDER BY pi.pi_serial
Option 1: Create a "Running Total" field in Crystal Reports to sum up only one "sales_value" per "proforma_invoice_id".
Option 2: Add a helper column to your Postgresql query like so:
case
when row_number()
over (partition by proforma_invoice_id
order by manufacturing_order_master_id)
= 1
then sales_value
else 0
end
as sales_value
I prepared this SQLFiddle with an example for you (and would of course like to encourage you to do the same for your next db query related question on SO, too :-)

T-SQL with GROUP BY, HAVING and COUNT in LINQ syntax

Im struggling converting a T-SQL query into LINQ syntax.
In T-SQL the query looks like this:
WITH FailedFiles AS
(
SELECT 1 AS FileExists
FROM [FileHistory] f
INNER JOIN [Users] u ON f.UerId = u.UserId
GROUP by f.FileName
HAVING SUM(CASE f.FileState WHEN 1 /*Success*/ THEN 1 ELSE 0 END) <= 0
AND SUM(CASE f.FileState WHEN 2 /*Failed*/ THEN 1 ELSE 0 END) >= 1
)
SELECT COUNT(1) from FailedFiles
Having serious troubles converting the T-SQL above into LINQ (doesnt matter if query syntax or method syntax). Can someone give me a hint how the correct order and nesting of the LINQ query should look like?
what the query actually does:
I have a file history table with multiple entries for a individual file. Need to know how many failed files there are in total. Meaning a files never processed sucessfully (state 1) and at least once processed with an error (state 2). single files are grouped by file name. The query result is a single number.
Below query should work in theory. But it may fail depending on the version of Entity Framework and the Provider.
var count = (from f in context.FileHistory
join u in context.User on f.UserId equals u.UserId
select f)
.GroupBy(f=> f.FileName)
.Where(g=>
g.Count(i=> i.FileState == 1) <=0 &&
g.Count(i=> i.FileState == 2) >=1 ).Count();

SQLITE : Optimize ORDER BY Query

All,
I am iOS developer. Currently we have stored 2.5 lacks data in database. And we have implemented search functionality on that. Below is the query that we are using.
select CustomerMaster.CustomerName ,CustomerMaster.CustomerNumber,
CallActivityList.CallActivityID,CallActivityList.CustomerID,CallActivityList.UserID,
CallActivityList.ActivityType,CallActivityList.Objective,CallActivityList.Result,
CallActivityList.Comments,CallActivityList.CreatedDate,CallActivityList.UpdateDate,
CallActivityList.CallDate,CallActivityList.OrderID,CallActivityList.SalesPerson,
CallActivityList.GratisProduct,CallActivityList.CallActivityDeviceID,
CallActivityList.IsExported,CallActivityList.isDeleted,CallActivityList.TerritoryID,
CallActivityList.TerritoryName,CallActivityList.Hours,UserMaster.UserName,
(FirstName ||' '||LastName) as UserNameFull,UserMaster.TerritoryID as UserTerritory
from
CallActivityList
inner join CustomerMaster
ON CustomerMaster.DeviceCustomerID = CallActivityList.CustomerID
inner Join UserMaster
On UserMaster.UserID = CallActivityList.UserID
where
(CustomerMaster.CustomerName like '%T%' or
CustomerMaster.CustomerNumber like '%T%' or
CallActivityList.ActivityType like '%T%' or
CallActivityList.TerritoryName like '%T%' or
CallActivityList.SalesPerson like '%T%' )
and CallActivityList.IsExported!='2' and CallActivityList.isDeleted != '1'
order by
CustomerMaster.CustomerName
limit 50 offset 0
Without using 'order by' The query is returning result in 0.5 second. But when i am attaching 'order by', Time is increasing to 2 seconds.
I have tried indexing but it is not making any noticeable change. Any one please help. If we are not going through Query then how can we do it fast.
Thanks in advance.
This is due to the the limit. Without ORDER BY only 50 records have to be processed and any 50 will be returned. With ORDER BY all the records have to be processed in order to determine which ones are the first 50 (in order).
The problem is that the ORDER BY is performed on a joined table. Otherise you could apply the limit on the main table (I assume it is the CallActivityList) first and then join.
SELECT ...
FROM
(SELECT ... FROM CallActivityList ORDER BY ... LIMIT 50 OFFSET 0) AS CAL
INNER JOIN CustomerMaster ON ...
INNER JOIN UserMaster ON ...
ORDER BY ...
This would reduce the costs for joining the tables. If this is not possible, try at least to join CallActivityList with CustomerMaster. Apply the limit to those and finally join with UserMaster.
SELECT ...
FROM
(SELECT ...
FROM
CallActivityList
INNER JOIN CustomerMaster ON ...
ORDER BY CustomerMaster.CustomerName
LIMIT 50 OFFSET 0) AS ActCust
INNER JOIN UserMaster ON ...
ORDER BY ...
Also, in order to make the ordering unambiguous, I would include more columns into the order by, like call date and call id. Otherwise this could result in a inconsistent paging.

How to use GROUP BY with Firebird?

I'm trying create a SELECT with GROUP BY in Firebird but I can't have any success. How could I do this ?
Exception
Can't format message 13:896 -- message file C:\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause).
(49,765 sec)
trying
SELECT FA_DATA, FA_CODALUNO, FA_MATERIA, FA_TURMA, FA_QTDFALTA,
ALU_CODIGO, ALU_NOME,
M_CODIGO, M_DESCRICAO,
FT_CODIGO, FT_ANOLETIVO, FT_TURMA
FROM FALTAS Falta
INNER JOIN ALUNOS Aluno ON (Falta.FA_CODALUNO = Aluno.ALU_CODIGO)
INNER JOIN MATERIAS Materia ON (Falta.FA_MATERIA = Materia.M_CODIGO)
INNER JOIN FORMACAOTURMAS Turma ON (Falta.FA_TURMA = Turma.FT_CODIGO)
WHERE (Falta.FA_CODALUNO = 238) AND (Turma.FT_ANOLETIVO = 2015)
GROUP BY Materia.M_CODIGO
Simple use of group by in firebird,group by all columns
select * from T1 t
where t.id in
(SELECT t.id FROM T1 t
INNER JOIN T2 j ON j.id = t.jid
WHERE t.id = 1
GROUP BY t.id)
Using GROUP BY doesn't make sense in your example code. It is only useful when using aggregate functions (+ some other minor uses). In any case, Firebird requires you to specify all columns from the SELECT column list except those with aggregate functions in the GROUP BY clause.
Note that this is more restrictive than the SQL standard, which allows you to leave out functionally dependent columns (ie if you specify a primary key or unique key, you don't need to specify the other columns of that table).
You don't specify why you want to group (because it doesn't make much sense to do it with this query). Maybe instead you want to ORDER BY, or you want the first row for each M_CODIGO.

DB2 subquery not working using IN statement SQLCODE 115

I'm trying to execute a query in DB2. But it throws following error:
Error: DB2 SQL Error: SQLCODE=-115, SQLSTATE=42601, SQLERRMC=IN, DRIVER=4.8.86
SQLState: 42601
ErrorCode: -115
Error: DB2 SQL Error: SQLCODE=-514, SQLSTATE=26501, SQLERRMC=SQL_CURSH200C1; STMT0001, DRIVER=4.8.86
SQLState: 26501
ErrorCode: -514
Which does'nt make sense as my query looks correct:
SELECT ROW_NUMBER() OVER() AS ID,
CONCAT(TRIM(TB1.ROW1),CONCAT('_',TRIM(TB1.ROW2))) AS CODE_DESCRIPTION,
CASE
WHEN TRIM(TB1.ROW1) IN (SELECT T1.ROW1 FROM DB1.TABLE1 T1 WHERE T1.ROW3 = 'TEST')
THEN 'Valid'
ELSE 'Invalid'
END,
TB1.* FROM DB1.TABLE1 TB1
WHERE TB1.ROW3 = 'CLASS1';
SQLCode 115 means Comparison is invalid. Which is not ?
Update:
What I'm trying to accomplish here is. I have a Table Table1(Name changed for simplicity). Following is the part of the content.
**Row3** **Row1** **Row2**
KSASPREM SRQ 0 0 Auto Carry SRQ
KSASPREM SCG 0 0 BRT Buses SCG
KSASPREM SCE 0 0 Buses SCE
KSASPREM SRR 0 0 Buses SRR
KSASPREM SDC 0 0 Domestic All Risks SDC
KSASPREM SDA 0 0 Domestic Buildings SDA
Task to accomplish:
Retrieve all the values from Table1 where Row3 is KSASPREM
The result should contain one extra column 'Valid' value Yes/No if value of Row1 is not in the Values retrieved from Table1 where Row3 is 'TEST'
Hope I made myself clear and not more confusing ?
Any Help ?
Thanks
Ps. Updated the Query
As with so many things, a JOIN (here, LEFT JOIN) is the answer. Specifically, we need to put the (slightly modified) subquery as the table reference:
LEFT JOIN (SELECT DISTINCT row1, 'Valid' as valid
FROM Table1
WHERE row3 = 'TEST') AS Test
ON Test.row1 = TB1.row1
LEFT JOIN tells the query engine that "rows in this other table aren't required".
DISTINCT says, "for all value combinations in these columns, give me just one row"
Using a constant value - 'Valid' - returns that constant value.
... so this gets us a (virtual, temp) table containing unique row1 entries where row3 = 'test'.
Here's the full query:
SELECT ROW_NUMBER() OVER(ORDER BY TB1.row1) AS ID,
TRIM(TB1.ROW1) || '_' || TRIM(TB1.ROW2) AS CODE_DESCRIPTION,
COALESCE(Test.valid, 'Invalid') AS valid,
TB1.row3, TB1.row1, TB1.row2
FROM Table1 TB1
LEFT JOIN (SELECT DISTINCT row1, 'Valid' as valid
FROM Table1
WHERE row3 = 'TEST') Test
ON Test.row1 = TB1 .row1
WHERE TB1.ROW3 = 'KSASPREM'
SQL Fiddle Example
COALESCE(...) returns the first non-null value encountered in the value list. Since, if there is no Test row, Test.valid will be null, this outputs 'Invalid' for TB1 rows without a corresponding Test row. (Internally it's calling CASE, I believe, this just makes it prettier)
Note that:
I've put an ORDER BY into the OVER clause, to return (mostly) consistent results. If you only ever plan on running this once it doesn't matter, but if you need to run it multiple times and get consistent IDs, you'll need to use something that won't be shuffled.
DB2 (and apparently PostgreSQL) support || as a concat operator. It makes reading statements so much easier to understand.
Never use SELECT *, it isn't safe for several reasons. Always specify which columns you want.