MySQL query: Using UNION and getting row number as part of SELECT - mysql

I have a union query as follows:
(SELECT t.id, t.name, c.company AS owner, t.creation_date AS date, t.notes
FROM tool t, client c
WHERE t.id_customer = '15' AND t.trash_flag = '1')
UNION
(SELECT f.id, f.name, CONCAT(m.first_name, ' ', m.last_name) AS owner, f.date, f.notes
FROM file f, meta m
WHERE ((f.acl = 0) OR (f.acl = 1 AND '1' = TRUE) OR (f.acl = 2 AND f.id = '7')) AND f.id = '15' AND f.trash_flag = '1' AND m.user_id = f.id_user)
ORDER BY 'name' 'ASC' LIMIT 0,20
Everything works fine but I have two questions:
How do I add a column to the entire result set that gives the row number
Could I do this without using UNION e.g. an advanced join?
Thanks for your time MySQL gurus!

I can't test it righ now but from what I found, following might work:
Reference: Row Number Variable
SQL Statement
SELECT #rownum := #rownum + 1 rownum
, t.*
FROM (
(SELECT t.id
, t.name
, c.company AS owner
, t.creation_date AS date
, t.notes
FROM tool t
, client c
WHERE t.id_customer = '15'
AND t.trash_flag = '1'
) UNION (
SELECT f.id
, f.name
, CONCAT(m.first_name, ' ', m.last_name) AS owner
, f.date
, f.notes
FROM file f
, meta m
WHERE ((f.acl = 0) OR (f.acl = 1 AND '1' = TRUE) OR (f.acl = 2 AND f.id = '7')) AND f.id = '15' AND f.trash_flag = '1' AND m.user_id = f.id_user)
)
) t
, (SELECT #rownum := 0) r
ORDER BY
'name' ASC
LIMIT 0, 20

Related

UNION Tables MySQL and output into JSON Array

I need some help on MySQL Query for UNION multiple Tables and group the result by ID and output the result in JSON_ARRAY. I have referred to this but I can't get the output as I want because my query need to UNION tables.
SELECT
JSON_ARRAYAGG(JSON_OBJECT(
'_CODE', a._CODE,
'_USERID', a._USERID,
'_NAME', c._NAME,
'HAHA',
(SELECT JSON_ARRAY(JSON_OBJECT(
'_CAT', b._CAT,
'_MODEL', b._MODEL,
'_SERIAL', b._SERIAL,
'_IPADDR', b._IPADDR,
'_OS', (SELECT _DESC
FROM kod_produk
WHERE _CODE = (SELECT _PROD
FROM inventori_dt3
WHERE _CODE = a._CODE
AND _CAT = '15'
AND _SERIAL = b._SERIAL)),
'_AV', (SELECT CONCAT(_DESC,
' (',
(CASE WHEN(SELECT _CODE
FROM inventori_dt3
WHERE _CODE = a._CODE
AND _CAT = '16'
AND _EXPY_DATE > NOW())
IS NOT NULL
THEN
'AKTIF'
ELSE
'TAMAT'
END), ')')
FROM kod_produk
WHERE _CODE = (SELECT _PROD
FROM inventori_dt3
WHERE _CODE = a._CODE
AND _CAT = '16'
AND _SERIAL = b._SERIAL))
)))
)) Z
FROM
inventori_mt a
LEFT JOIN
(
SELECT _CODE, _CAT, _MODEL, _SERIAL, _IPADDR FROM inventori_dt1
UNION ALL
SELECT _CODE, _CAT, _MODEL, _SERIAL, _IPADDR FROM inventori_dt2
) b ON a._CODE = b._CODE
LEFT JOIN
sys_pengguna c ON a._USERID = c._USERID
Table design
Pastebin
Expected Result
Actual Output Result
DB-Fiddle
Sample DB
Need to use JSON_ARRAY() with JSON_ARRAYAGG() within the subquery, and use GROUP BY expression within the one level outer query with JSON_OBJECT() function at topmost of this query in order to get each individual grouped, and nested objects. And apply JSON_ARRAYAGG() at the outermost level in order to aggregate all those independent JSON object pieces. So, use :
SELECT JSON_PRETTY( JSON_ARRAYAGG(Z) ) AS Z
FROM
(
SELECT
JSON_OBJECT(
'_CODE', a._CODE,
'_USERID', a._USERID,
'_NAME', c._NAME,
'HAHA',
(SELECT
JSON_ARRAYAGG(
JSON_OBJECT(
'_CAT', b._CAT,
'_MODEL', b._MODEL,
'_SERIAL', b._SERIAL,
'_IPADDR', b._IPADDR ,
'_OS', (SELECT _DESC
FROM kod_produk
WHERE _CODE = (SELECT _PROD
FROM inventori_dt3
WHERE _CODE = a._CODE
AND _CAT = '15'
AND _SERIAL = b._SERIAL)),
'_AV', (SELECT CONCAT(_DESC,
' (',
(CASE WHEN(SELECT _CODE
FROM inventori_dt3
WHERE _CODE = a._CODE
AND _CAT = '16'
AND _EXPY_DATE > NOW())
IS NOT NULL
THEN
'AKTIF'
ELSE
'TAMAT'
END), ')')
FROM kod_produk
WHERE _CODE = (SELECT _PROD
FROM inventori_dt3
WHERE _CODE = a._CODE
AND _CAT = '16'
AND _SERIAL = b._SERIAL))
)
)
)
) Z
FROM inventori_mt a
LEFT JOIN
(
SELECT _CODE, _CAT, _MODEL, _SERIAL, _IPADDR FROM inventori_dt1
UNION ALL
SELECT _CODE, _CAT, _MODEL, _SERIAL, _IPADDR FROM inventori_dt2
) b
ON a._CODE = b._CODE
LEFT JOIN sys_pengguna c
ON a._USERID = c._USERID
GROUP BY a._CODE, a._USERID, c._NAME
) q
Demo

MySQL Union query: PASSING TEMP ClaimID field value to TEMP1 table ClaimID in one union query

CREATE DEFINER=`root`#`localhost` PROCEDURE `SP_DupAuditCriteria_1`()
BEGIN
set #RowNbr=concat(date_format(curdate(),'%Y%m%d'),'0000000');
select temp.* from
(SELECT c.*, concat(c.VendorID,a.VendorID) as MergeH200A, concat(a.VendorID,c.VendorID) as MergeH200B, 'New' as Record_Type, #RowNbr:= #RowNbr + 1 AS ClaimID
FROM tbldupaudit_currentitems AS c
inner join tbldupaudit_archiveitems a
on c.InvoiceID = a.InvoiceID
and c.GrossAmount = a.GrossAmount) as temp
inner join tbldupaudit_archiveitems b
on temp.InvoiceID = b.InvoiceID
and temp.GrossAmount = b.GrossAmount
and temp.VendorID = b.VendorID
and temp.VoucherID <> b.VoucherID
Union all
select temp1.* from
(SELECT f.*, concat(f.VendorID,d.VendorID) as MergeH200A, concat(d.VendorID,f.VendorID) as MergeH200B, 'ARCHIVE' as Record_Type, 1 AS ClaimID
FROM tbldupaudit_archiveitems AS f
inner join tbldupaudit_currentitems d
on f.InvoiceID = d.InvoiceID
and f.GrossAmount = d.GrossAmount) as temp1
inner join tbldupaudit_currentitems e
on temp1.InvoiceID = e.InvoiceID
and temp1.GrossAmount = e.GrossAmount
and temp1.VendorID = e.VendorID
and temp1.VoucherID <> e.VoucherID
order by InvoiceID, Record_Type DESC;
END
trying make unique ClaimID for each pair. I am able to generate sequential number for first half union all but same ClaimID not able to generate in other half Union all.
Please help me in how to create/generate one unique ID for matched items.
Thank you!]1
In the second select ( after the UNION ALL) you are not incrementing a var so if you want both value incrementeedc the try using a var also for the second
select temp.*
from (
SELECT c.*, concat(c.VendorID,a.VendorID) as MergeH200A, concat(a.VendorID,c.VendorID) as MergeH200B, 'New' as Record_Type
, #RowNbr:= #RowNbr + 1 AS ClaimID
FROM tbldupaudit_currentitems AS c
inner join tbldupaudit_archiveitems a on c.InvoiceID = a.InvoiceID
and c.GrossAmount = a.GrossAmount
) as temp
inner join tbldupaudit_archiveitems b on temp.InvoiceID = b.InvoiceID
and temp.GrossAmount = b.GrossAmount
and temp.VendorID = b.VendorID
and temp.VoucherID <> b.VoucherID
Union all
select temp1.*
from (
SELECT f.*, concat(f.VendorID,d.VendorID) as MergeH200A, concat(d.VendorID,f.VendorID) as MergeH200B, 'ARCHIVE' as Record_Type
, #RowNbr:= #RowNbr + 1 AS ClaimID
FROM tbldupaudit_archiveitems AS f
inner join tbldupaudit_currentitems d on f.InvoiceID = d.InvoiceID
and f.GrossAmount = d.GrossAmount
) as temp1
inner join tbldupaudit_currentitems e on temp1.InvoiceID = e.InvoiceID
and temp1.GrossAmount = e.GrossAmount
and temp1.VendorID = e.VendorID
and temp1.VoucherID <> e.VoucherID
order by InvoiceID, Record_Type DESC;
Modelling example - see fiddle :
SELECT CONCAT( 'prefix', LPAD( CASE #prev
WHEN #prev := InvoiceID
THEN #num
ELSE #num := #num + 1
END, 8, '0' ) ) ClaimID, InvoiceID, Amount, FromTable
FROM ( SELECT InvoiceID, Amount, 'CurrentItems' FromTable
FROM CurrentItems
UNION ALL
SELECT InvoiceID, Amount, 'ArchivedItems'
FROM ArchivedItems
WHERE EXISTS ( SELECT NULL
FROM CurrentItems
WHERE CurrentItems.InvoiceID = ArchivedItems.InvoiceID) ) unioned,
( SELECT #prev := 0, #num := 1000 ) variables
ORDER BY InvoiceID, FromTable DESC;

Multi dynamic rows into multi column MySQL

I'm using MySQL. I have to separate multi repeated rows into columns. The table has following structure.
But I need like this.
Note: There will be always 6 records of each DateTime. But Title and Feedback are dynamic. I tried to use
select DateTime,
But this is not giving my expected value. I wrote a code (not considered about title):
select
g.dateTime AS dateTime,
g.feedback as feedback ,
c.title AS title
from gauge g
inner join category c on g.category_id=c.category_id AND c.title ='title' AND g.feedback ='feedback'
group by g.dateTime
This doesn't work and I tried GROUP_CONCAT(.... SEPARATOR'.....' ) this gives me not expected output, just gives output in one column. My approach might be wrong.
Use a dynamic pivot since there are many different values
Fiddle to play with
drop table t;
create table t
(
dateTime datetime,
title varchar(50),
feedback int
);
insert into t values
( '2018-06-29 12:55:36', 'A', 1),
( '2018-06-29 12:55:36', 'B', 2),
( '2018-06-22 12:55:36', 'A', 1),
( '2018-06-22 12:55:36', 'B', 2),
( '2018-06-22 12:55:36', 'C', 3);
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN title = ''',
title,
''' THEN ''', title ,''' END) AS ',
CONCAT(' Title',title,',')
),
CONCAT(
'MAX(CASE WHEN feedback = ''',
feedback,
''' THEN ''', feedback ,''' END) AS ',
CONCAT(' Feedback',feedback)
)
) INTO #sql
FROM T;
SET #sql = CONCAT('SELECT dateTime, ', #sql, '
FROM t
GROUP BY dateTime');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I would simply use conditional aggregation. Enumerating the values is a bit tricky in MySQL (unless you are using MySQL 8+):
select datetime,
max(case when rn = 1 then title end) as title_1,
max(case when rn = 1 then feedback end) as feedback_1,
max(case when rn = 2 then title end) as title_2,
max(case when rn = 2 then feedback end) as feedback_2,
max(case when rn = 3 then title end) as title_3,
max(case when rn = 3 then feedback end) as feedback_3,
max(case when rn = 4 then title end) as title_4,
max(case when rn = 4 then feedback end) as feedback_4,
max(case when rn = 5 then title end) as title_5,
max(case when rn = 5 then feedback end) as feedback_5,
max(case when rn = 6 then title end) as title_6,
max(case when rn = 6 then feedback end) as feedback_6
from (select gc.*,
(#rn := if(#dt = g.dateTime, #rn + 1,
if(#dt := g.dateTime, 1, 1)
)
) as rn
from (select g.dateTime, g.feedback, c.title AS title
from gauge g inner join
category c
on g.category_id = c.category_id and
c.title = 'title' and
g.feedback = 'feedback'
group by g.dateTime
order by g.dateTime
) gc cross join
(select #dt := '', #rn := 0) params
) gc
group by datetime;
I don't think the filtering on c.title and g.feedback is correct.
Not an optimized approach but you may join them into table and filter according to row number modulo by 6. This way, we can separate the 6 rows into 6 different table
http://rextester.com/DLVV64095
SELECT MAIN.DateTime,
TBL1.TITLE AS Title1,
TBL1.FEEDBACK AS Feedback1,
TBL2.TITLE AS Title2,
TBL2.FEEDBACK AS Feedback2,
TBL3.TITLE AS Title3,
TBL3.FEEDBACK AS Feedback3,
TBL4.TITLE AS Title4,
TBL4.FEEDBACK AS Feedback4,
TBL5.TITLE AS Title5,
TBL5.FEEDBACK AS Feedback5,
TBL6.TITLE AS Title6,
TBL6.FEEDBACK AS Feedback6
FROM (
SELECT [DATETIME] AS [DateTime]
FROM GAUGE
GROUP BY [DATETIME]
) MAIN
INNER JOIN (
SELECT G.DATETIME,
G.FEEDBACK,
C.TITLE,
ROW_NUMBER() OVER(PARTITION BY ORDER BY (SELECT 1) ASC) AS ROWNO
FROM GAUGE G
INNER JOIN CATEGORY C
ON G.CATEGORY_ID = C.CATEGORY_ID
) TBL1
ON TBL1.DATETIME = MAIN.[DateTime]
AND TBL1.ROWNO % 6 = 1
INNER JOIN (
SELECT G.DATETIME,
G.FEEDBACK,
C.TITLE,
ROW_NUMBER() OVER(PARTITION BY ORDER BY (SELECT 1) ASC) AS ROWNO
FROM GAUGE G
INNER JOIN CATEGORY C
ON G.CATEGORY_ID = C.CATEGORY_ID
) TBL2
ON TBL2.DATETIME = MAIN.[DateTime]
AND TBL2.ROWNO % 6 = 2
INNER JOIN (
SELECT G.DATETIME,
G.FEEDBACK,
C.TITLE,
ROW_NUMBER() OVER(PARTITION BY ORDER BY (SELECT 1) ASC) AS ROWNO
FROM GAUGE G
INNER JOIN CATEGORY C
ON G.CATEGORY_ID = C.CATEGORY_ID
) TBL3
ON TBL3.DATETIME = MAIN.[DateTime]
AND TBL3.ROWNO % 6 = 3
INNER JOIN (
SELECT G.DATETIME,
G.FEEDBACK,
C.TITLE,
ROW_NUMBER() OVER(PARTITION BY ORDER BY (SELECT 1) ASC) AS ROWNO
FROM GAUGE G
INNER JOIN CATEGORY C
ON G.CATEGORY_ID = C.CATEGORY_ID
) TBL4
ON TBL4.DATETIME = MAIN.[DateTime]
AND TBL4.ROWNO % 6 = 4
INNER JOIN (
SELECT G.DATETIME,
G.FEEDBACK,
C.TITLE,
ROW_NUMBER() OVER(PARTITION BY ORDER BY (SELECT 1) ASC) AS ROWNO
FROM GAUGE G
INNER JOIN CATEGORY C
ON G.CATEGORY_ID = C.CATEGORY_ID
) TBL5
ON TBL5.DATETIME = MAIN.[DateTime]
AND TBL5.ROWNO % 6 = 5
INNER JOIN (
SELECT G.DATETIME,
G.FEEDBACK,
C.TITLE,
ROW_NUMBER() OVER(PARTITION BY ORDER BY (SELECT 1) ASC) AS ROWNO
FROM GAUGE G
INNER JOIN CATEGORY C
ON G.CATEGORY_ID = C.CATEGORY_ID
) TBL6
ON TBL6.DATETIME = MAIN.[DateTime]
AND TBL6.ROWNO % 6 = 0

Optimising MYSQL query with row number

SELECT o.* FROM ( SELECT
#rownum := #rownum + 1 RN,
i.* FROM<br>
(
SELECT
#rownum:=0
)
r,<br>
(
SELECT DISTINCT<br>
CG_MGR_USR.MANAGER_NAME,<br>
CG_MGR_USR.PARAM_NAME,<br>
USR_TR_DATA.USER_ID,<br>
CG_MGRS.FIRST_NAME,<br>
CG_MGRS.LAST_NAME,<br>
CC_GENOBJ.OBJNAME,<br>
USR_TR_DATA.RISK_ID,<br>
USR_TR_DATA.VERSION_ID,<br>
T_RISK.RISK_DESCR,<br>
CC_RISKT.RISK_ID CC_RISK,<br>
CC_RISKT.DESCN,<br>
USR_TR_DATA.SYSTEM_ID,<br>
T_STATUS.STATUS,<br>
USR_TR_DATA.COUNTS,<br>
SYSTEMS.SYSTEM_NAME<br>
FROM
TABLE_USR_TR_DATA USR_TR_DATA<br>
LEFT OUTER JOIN TABLE_CC_GENOBJ CC_GENOBJ<br>
ON
CC_GENOBJ.GENOBJTP = 1
AND CC_GENOBJ.SYSTEM_ID IN<br>
(
SELECT
sys_id
FROM
TABLE_CS_SYSTEM
WHERE
cs_sys_id =USR_TR_DATA.system_id
AND is_primary='Y'
)<br>
AND CC_GENOBJ.GENOBJID = USR_TR_DATA.USER_ID,<br>
TABLE_RISK T_RISK<br>
LEFT OUTER JOIN TABLE_CC_RISKT CC_RISKT
ON<br>
CC_RISKT.LANG = 'EN'
AND T_RISK.CC_RISK_ID = CC_RISKT.RISK_ID,<br>
TABLE_CG_MGR_USR CG_MGR_USR,<br>
TABLE_CG_MGRS CG_MGRS,<br>
TABLE_STATUS T_STATUS,<br>
TABLE_CS_SYSTEM CS_SYSTEMS,<br>
TABLE_SYSTEMS SYSTEMS<br>
WHERE
USR_TR_DATA.RISK_ID = T_RISK.RISK_ID<br>
AND USR_TR_DATA.VERSION_ID = T_RISK.VERSION_ID<br>
AND CG_MGR_USR.USER_NAME = USR_TR_DATA.USER_ID<br>
AND CG_MGR_USR.SYSTEM_ID = CS_SYSTEMS.SYS_ID<br>
AND CG_MGRS.MANAGER_NAME = CG_MGR_USR.MANAGER_NAME<br>
AND CG_MGRS.PARAM_NAME =CG_MGR_USR.PARAM_NAME<br>
AND CG_MGRS.SYSTEM_ID = CG_MGR_USR.SYSTEM_ID<br>
AND CS_SYSTEMS.CS_SYS_ID = USR_TR_DATA.SYSTEM_ID<br>
AND CS_SYSTEMS.IS_PRIMARY = 'Y'<br>
AND T_STATUS.SEQ_NO = USR_TR_DATA.STATUS_ID<br>
AND SYSTEMS.SYSTEMS_ID = USR_TR_DATA.SYSTEM_ID<br>
AND CG_MGR_USR.MANAGER_NAME IN( 'SAPUSER' )<br>
AND T_STATUS.STATUS IN( 'IN-PROCESS', 'OPEN' )<br>
AND USR_TR_DATA.COUNTS >= 1<br>
ORDER BY
USER_ID,
SYSTEM_ID,
RISK_ID,
VERSION_ID,
CC_RISK,
STATUS,
COUNTS ASC
)
i ) o <br>WHERE o.RN >= 1 AND o.RN <= 10
It is taking too much time for to fetch only 10 records.

how I can get the next data in mysql

really do not know if you can, but i I need the DATE VENC to be equal to '2013-02-02'.
the values of the column date_pay:
1-2013-01-01
2-2013-02-02
3-0000-00-00
4-0000-00-00
this is my query:
SELECT s.id,
s.name,
s.nro_s,
ts.cat,
SUM( ts.pryce ) AS deuda,
SUM( ts.pryce ) DIV ts.pryce AS c_p,
date_venc = (select max(date_pay) from c ) // the date in question
FROM s
INNER JOIN c
INNER JOIN ts
WHERE s.id = '123'
AND c.id = '123'
AND c.date_pay = '0000-00-00'
AND s.ts = ts.id_ts
Sorry for my english, is very basic.
Greetings.
Assuming date_venc is DATE a possible solution
select *
from s
where s.date_venc=
(select max(cast(SUBSTRING_INDEX(date_pay,'-',-3)as DATE))from c);
also check out sqlfiddle
http://sqlfiddle.com/#!2/64197/1
and your query should probably be modified to,
SELECT s.id,
s.name,
s.nro_s,
ts.cat,
SUM( ts.pryce ) AS deuda,
SUM( ts.pryce ) DIV ts.pryce AS c_p,
date_venc
FROM s
INNER JOIN c
INNER JOIN ts
WHERE s.id = '123'
AND c.id = '123'
AND c.date_pay = '0000-00-00'
AND s.ts = ts.id_ts
AND date_venc = (select max(cast(SUBSTRING_INDEX(date_pay,'-',-3)as DATE)) from c ) // the date in question