SQLITE query GROUP BY with SUM Using Delphi and Zeos - sqlite

I have an app created using Delphi XE3 accessing the SQLite database with Zeos Component.
A select command in SQLite that return 3 rows:
select p.descricao, pg.valor
from pagamento pg
inner join venda v on pg.origem = 'venda' and v.id_venda = pg.id_origem
left join pagamento_tipo p on pg.id_pagamento_tipo = p.id_pagamento_tipo
where v.data >= '2021-01-19' and v.data <= '2021-01-19'
and v.ra_status_venda in ( 'Finalizado', 'Pedido')
but when I put the group command the information result is wrong.
select p.descricao, sum(pg.valor) as valor
from pagamento pg
inner join venda v on pg.origem = 'venda' and v.id_venda = pg.id_origem
left join pagamento_tipo p on pg.id_pagamento_tipo = p.id_pagamento_tipo
where v.data >= '2021-01-19' and v.data <= '2021-01-19'
and v.ra_status_venda in ( 'Finalizado', 'Pedido')
group by descricao
the P02 not sum.
and, if I sum all row, without group by, the value was correct too.
select sum(pg.valor) as valor
from pagamento pg
inner join venda v on pg.origem = 'venda' and v.id_venda = pg.id_origem
left join pagamento_tipo p on pg.id_pagamento_tipo = p.id_pagamento_tipo
where v.data >= '2021-01-19' and v.data <= '2021-01-19'
and v.ra_status_venda in ( 'Finalizado', 'Pedido')
PS: in another period this commands sum correctly.
PS2 I'm using dll 32bits for windows.

With tips #Shawn and #forpas I solve this problem, the SQLite type of field NUMERIC converts the numbers to other types in the RUNTIME select command, how the two first values were INTEGER and the last value were Real, apparently my program not recognize two different types in the same column.
To solve I change the type of field in the database from NUMERIC to REAL.

Related

what is different between using Variable and not in Mariadb?

I just want to get some hint. Is there a type issue?
issue case.
SET #ids = '4094,8562,11144,3017,5815,11121,1957,4095,8563,11145,3018,5816,8527,11122,1959,4096,8564,3020,5817,8528,11123,1961,4097,8571,3021,6020,8535,11128,1962,5181,8572,3581,6021';
this #ids value is actually collected by GROUP_CONCAT() from the subquery;
SELECT
ifnull(sum(case when a.student IS NOT NULL then total END), 0)
from
tb_class a
WHERE
a.id IN (#ids)
and a.date >= '2023-02-01' AND a.DATE <= '2023-02-02'
==> 0
correct case2.
SELECT
ifnull(sum(case when a.student IS NOT NULL then total END), 0)
from
tb_class a
WHERE
a.id IN (4094,8562,11144,3017,5815,11121,1957,4095,8563,11145,3018,5816,8527,11122,1959,4096,8564,3020,5817,8528,11123,1961,4097,8571,3021,6020,8535,11128,1962,5181,8572,3581,6021)
and a.date >= '2023-02-01' AND a.DATE <= '2023-02-02'
==> 54
I got answer from googling. use function FIND_IN_SET()
SELECT
ifnull(sum(case when a.student IS NOT NULL then total END), 0)
from
tb_class a
WHERE
FIND_IN_SET(a.id, #ids)
and a.date >= '2023-02-01' AND a.DATE <= '2023-02-02'
Variables store single values, not lists. Your #ids is just a string that happens to have a comma separated list of numbers. The IN operator only compares against an explicit list; what you are doing is no different than a.id = #ids (which will actually be true, with a warning, for the first number in the list if id is a numeric type, since the string will be converted to a number and the trailing non-numeric portion discarded).
Sometimes you do want to work with a string containing a list of ids such as this, for instance if you have a query that reads many rows that you want to use to produce a small list of ids to update, without the update locking those all the rows read. Then you can use dynamic sql:
SET #ids = '4094,8562,...';
SET #sql = concat('select * from a where a.id in (',#ids,')');
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
Or, in mariadb since 10.2,
EXECUTE IMMEDIATE concat('select * from a where a.id in (',#ids,')');
Another alternative is to use FIND_IN_SET, as shown in another answer, but that will not use an index to look up ids, so may be inefficient.

Oracle Json object DISTINCT keep getting repeating columns

So i have a query and it need to return a JSON object but the DISTINCT doesn't work no matter what I try. I've been trying a series of other tests and no matter what the 'WBS' always shows up with 3 or more duplicated columns. Anyone got any ideas?
I am working in Asp.net 6 MVC
PROCEDURE GET_BASELINE_RPT (in_WBS_LEVEL_ID IN NUMBER, in_FISCAL_YEAR IN VARCHAR2,
in_FISCAL_MONTH IN VARCHAR2, RET OUT CLOB) AS
BEGIN
WITH cte AS (
SELECT /*+MATERIALIZE*/ DISTINCT L.WBS_LEVEL_ID
FROM
WBS_LEVEL L
)
SELECT
JSON_ARRAYAGG (
JSON_OBJECT (
'WBS' VALUE L.WBS_LEVEL_NAME,
'Title' VALUE W.DESCRIPTION,
'Rev' VALUE B.REV_NUMBER,
'ScopeStatus' VALUE W.STATUS,
'BCP' VALUE CASE WHEN BC.FISCAL_YEAR = 0 THEN '' ELSE
SUBSTR(BC.FISCAL_YEAR,3,2)||'-'||LPAD(BC.BCP_FISCAL_ID, 3, '0') END,
'BCPApprovalDate' VALUE BC.APPROVAL_DATE,
'Manager' VALUE P1.NICK_NAME,
'ProjectControlManager' VALUE P2.NICK_NAME,
'ProjectControlEngineer' VALUE P3.NICK_NAME,
'FiscalYear' VALUE W.FISCAL_YEAR,
'FiscalMonth' VALUE W.FISCAL_MONTH,
'WBSNumber' VALUE L.WBS_LEVEL_ID
)RETURNING CLOB)
INTO RET
FROM WBS_LEVEL L
LEFT OUTER JOIN BASELINE_RPT B ON L.WBS_LEVEL_ID = B.WBS_LEVEL_ID
JOIN BCP BC ON BC.BCP_ID = B.BCP_ID
LEFT OUTER JOIN WBS_TREE_MOD W ON L.WBS_LEVEL_ID = W.WBS_LEVEL_ID
LEFT OUTER JOIN VW_SITEPEOPLE P1 ON W.WBS_MANAGER_SNUMBER = P1.SNUMBER
LEFT OUTER JOIN VW_SITEPEOPLE P2 ON W.PCM_SNUMBER = P2.SNUMBER
LEFT OUTER JOIN VW_SITEPEOPLE P3 ON W.PCE_SNUMBER = P3.SNUMBER
ORDER BY L.WBS_LEVEL_NAME, B.REV_NUMBER DESC;
END GET_BASELINE_RPT;
so it turns out I wasn't getting duplicates at all. There were differences in the data but there were so many columns that had the same data that I didn't notice the differences until another review. I will try to restart my query but to be honest I may just put in a filter in my C#.

Peoplesoft Learning Management - First Time Pass Rate

We are working on PeopleSoft ELM 9.2 and I'm not finding what I need in any of the OOB queries so I'm attempting to build one. We need to get a "First Time Pass Rate" score, or the average of how many people pass a learning course on their first try. Ideally we would have the data for each attempt so that we could also see how many attempts a particular person or course has prior to getting a passing score.
Our setup includes SCORM 1.2 modules that pass off a score to the LMS for verification that a passing score was received. The closest I've been able to come so far is to get a "Pass/Fail" score but either my query unions are incorrect or the data is incorrect as it returns extraneous data that is not relevant to the other data returned or (if I force distinct values) it returns sporadically accurate data. Below is the SQL that I'm using if it helps.
Has anyone tried to build this kind of query before and how did you do it? :)
SELECT DISTINCT D1X.XLATLONGNAME, D.LM_ORGANIZATION_ID, D.LM_ORG_DESCR,
D.LM_HR_EMPLID, TO_CHAR(D.LM_HIRE_DT,'YYYY-MM-DD'), D.FIRST_NAME,
D.LAST_NAME, C.LM_CS_LONG_NM, C.LM_ACT_CD, A.LM_LC_LONG_NM, A.LM_LC_ID,
B12X.XLATLONGNAME, TO_CHAR(B.LM_COMPL_DT,'YYYY-MM-DD'), B.LM_ENRLMT_ID,
E15X.XLATLONGNAME
FROM PS_LM_LC A, PS_LM_ENRLMT B LEFT OUTER JOIN PSXLATITEM B12X ON
B12X.FIELDNAME='LM_STTS' AND B12X.FIELDVALUE=B.LM_STTS AND B12X.EFF_STATUS =
'A' AND B12X.EFFDT = (SELECT MAX(EFFDT) FROM PSXLATITEM TB WHERE
TB.FIELDNAME=B12X.FIELDNAME AND TB.FIELDVALUE=B12X.FIELDVALUE AND
TB.EFF_STATUS = 'A' AND TB.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-
DD'),'YYYY-MM-DD') ), PS_LM_ACT_CI_VW C, PS_LM_PERS_DTL_VW D LEFT OUTER JOIN
PSXLATITEM D1X ON D1X.FIELDNAME='LM_ACTIVE' AND D1X.FIELDVALUE=D.LM_ACTIVE
AND D1X.EFF_STATUS = 'A' AND D1X.EFFDT = (SELECT MAX(EFFDT) FROM PSXLATITEM
TB WHERE TB.FIELDNAME=D1X.FIELDNAME AND TB.FIELDVALUE=D1X.FIELDVALUE AND
TB.EFF_STATUS = 'A' AND TB.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-
DD'),'YYYY-MM-DD') ), PS_LM_ENR_LC_BL_VW E LEFT OUTER JOIN PSXLATITEM E15X
ON E15X.FIELDNAME='LM_PASS_STTS' AND E15X.FIELDVALUE=E.LM_PASS_STTS AND
E15X.EFF_STATUS = 'A' AND E15X.EFFDT = (SELECT MAX(EFFDT) FROM PSXLATITEM TB
WHERE TB.FIELDNAME=E15X.FIELDNAME AND TB.FIELDVALUE=E15X.FIELDVALUE AND
TB.EFF_STATUS = 'A' AND TB.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-
DD'),'YYYY-MM-DD') )
WHERE ( A.LM_ACT_ID = B.LM_ACT_ID
AND A.LM_ACT_ID = C.LM_ACT_ID
AND D.LM_PERSON_ID = B.LM_PERSON_ID
AND D.BUSINESS_UNIT IN ('00340','00235')
AND B.LM_ENRL_DT BETWEEN TO_DATE(:1,'YYYY-MM-DD') AND TO_DATE(:2,'YYYY-MM-DD')
AND D.LM_HR_EMPLID = :3
AND D.LM_ACTIVE = :4
AND B.LM_STTS = 'COMP'
AND A.LM_LC_ID = E.LM_LC_ID
AND E.LM_PASS_STTS IN ('FAIL','PASS'))

How to convert the Long value to String using sql

I am doing a long to string conversion using java in following way.
Long longValue = 367L;
String str = Long.toString(longValue, 36).toUpperCase();
this is returning me as value A7. how can achieve this in doing oracle sql.
UPDATED:
Hi, I have analyzed how java code is working then wanted to implement the same thing in procedure.
First point is Input vaues. LONG and Radix. in my case Radix is 36. so i will have values from 1..9A...Z0 It picks up the values from this set only.
Second point Long value as input. we have to divide this value with radix. if the quotient is more than 36 again we need to divide.
For eaxmple 367 then my converted value is 10(quotient) 7(remainder) that is A7.
3672 converted value is 102 0 i need to do again for 102 that is 2 -6 so my final value will be 2-6 0 that is 2U0(- means reverse the order).
UPDATE 2:
Using oracle built in functions we can do this. this was solved by my friend and gave me a function.I want to thank my friend. this will give me an out put as follows.
367 then my converted value is 10(quotient) 7(remainder) that is *A*7.(I modified this to my requirement).
FUNCTION ENCODE_STRING(BASE_STRING IN VARCHAR2,
FROM_BASE IN NUMBER,
TO_BASE IN NUMBER)
RETURN VARCHAR2
IS
V_ENCODED_STRING VARCHAR(100);
BEGIN
WITH N1 AS (
SELECT SUM((CASE
WHEN C BETWEEN '0' AND '9'
THEN TO_NUMBER(C)
ELSE
ASCII(C) - ASCII('A') + 10
END) * POWER(FROM_BASE, LEN - RN)
) AS THE_NUM
FROM (SELECT SUBSTR(BASE_STRING, ROWNUM, 1) C, LENGTH(BASE_STRING) LEN, ROWNUM RN
FROM DUAL
CONNECT BY ROWNUM <= LENGTH(BASE_STRING))
),
N2 AS (
SELECT (CASE
WHEN N < 10
THEN TO_CHAR(N)
ELSE CHR(ASCII('A') + N - 10)
END) AS DIGI, RN
FROM (SELECT MOD(TRUNC(THE_NUM/POWER(TO_BASE, ROWNUM - 1)), TO_BASE) N, ROWNUM RN
FROM N1
CONNECT BY ROWNUM <= TRUNC(LOG(TO_BASE, THE_NUM)) + 1)
)
SELECT SYS_CONNECT_BY_PATH(DIGI, '*') INTO V_ENCODED_STRING
FROM N2
WHERE RN = 1
START WITH RN = (SELECT MAX(RN) FROM N2)
CONNECT BY RN = PRIOR RN - 1;
RETURN V_ENCODED_STRING;
IN PL/SQL (or Oracle SQL) you have the a function called TO_CHAR.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions181.htm
It is not possible to do it in the pure SQL. You have to use PL/SQL.
Simple example how to do it PL/SQL:
CREATE TABLE long_tbl
(
long_col LONG
);
INSERT INTO long_tbl VALUES('How to convert the Long value to String using sql');
DECLARE
l_varchar VARCHAR2(32767);
BEGIN
SELECT long_col
INTO l_varchar
FROM long_tbl;
DBMS_OUTPUT.PUT_LINE(l_varchar);
END;
-- How to convert the Long value to String using sql
There is TO_LOB function but it can only by used when you insert data into table.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions185.htm
You can apply this function only to a LONG or LONG RAW column, and
only in the select list of a subquery in an INSERT statement.
There is also other, more proper way to do it by using "dbms_sql.column_value_long" but this gets complicated (fetching of the LONG column and appending to the CLOB type.)
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#i1025399
(Oracle Database PL/SQL Packages and Types Reference)

MySQL easy question CURDATE()

I want to compare two results
one is stored in the first query, and the other is exactly the same as the first, but i want only to recieve data < today
"SELECT s.GSP_nom as nom, timestamp, COUNT(s.GSP_nom) as nb_votes, AVG(v.vote+v.prix+v.serviceClient+v.interface+v.interface+v.services)/6 as moy
FROM votes_serveur AS v
INNER JOIN serveur AS s ON v.idServ = s.idServ
WHERE s.valide = 1
AND v.date < CURDATE()
GROUP BY s.GSP_nom
HAVING nb_votes > 9
ORDER BY moy DESC LIMIT 0,15";
is that correct ?
thank you
GROUP BY, not ROUP BY
v.date < CURDATE() looks o.k.

Resources