How to do union of multiple tables with where clause and order by in GORM (golang) - go

I'm trying to do union of multiple tables with selected columns and run where clause and order by clause on the resultset. How do I write this in GORM (Golang)
I tried the following snippet, but didn't run the where clause and order by clause in the DB query:
var union []map[string]interface{}
database.CONNECTION.Raw("? UNION ?",
database.CONNECTION.Select(ContentAttributes).Model(&model1{}),
database.CONNECTION.Select(ContentAttributes).Model(&model2{}),
).Where("id > ?", 1).Order("Name").Scan(&union)
N.B. ContentAttributes is a slice of string which contains the attributes I want to select.
It's running the following query:
SELECT "id","name","created_at","updated_at" FROM "model1" WHERE "model1"."deleted_at" IS NULL UNION SELECT "id","name","created_at","updated_at" FROM "model2" WHERE "model2"."deleted_at" IS NULL
I expected this to run the where condition and the order by clause on the union resultset. But it just did union and collected the results in the union variable. Please suggest a way to do this.

Not sure if this is the cleanest way to do it but it works.
var db = database.CONNECTION
var union []map[string]interface{}
var raw = "SELECT * (? UNION ?) union WHERE union.id > ? ORDER BY union.name"
db.Raw(raw,
db.Select("*").Model(&model1{}),
db.Select("*").Model(&model2{}),
1
).Scan(&union)

Related

using subquery factoring result in where clause

Why can't I use a subquery factoring clause result in the where clause of as depicted in the following sql:
with rpt as(
select * from reports where caseid =
:case_id and rownum=1 order by created desc
)
select
distinct rt.trialid
from
report_trials rt
join
trial_genes tg on rt.id=tg.trialid
where
rt.reportid = rpt.id
and
tg.gene not in('TMB','MS')
The subquery is named rptand used in the select statement's where clause. When executed encountering the following error: ORA-00904: "RPT"."ID": invalid identifier
UPDATE:
In fact nested query for the same thing is also giving me the same issue. The nested subquery is only returning a single column value from a single row:
select
distinct rt.trialid
from
report_trials rt
join
trial_genes tg on rt.id=tg.trialid
where
rt.reportid = (select id from reports where caseid = :case_id and
rownum=1 order by created desc)
and
tg.gene not in('TMB','MS')
You missed to add the table rpt in your query, thus that error.
with rpt as(
select * from reports where caseid =
:case_id and rownum=1 order by created desc
)
select
distinct rt.trialid
from
report_trials rt
join
trial_genes tg on rt.id=tg.trialid
join
rpt on rt.reportid = rpt.id
where
tg.gene not in('TMB','MS')

can I use `=` sign operator with sub-query instead of `IN`

I am just wondering if use = sign operator with sub-query instead of IN
Is it correct way ? and meet the oracle standard ?
Example
select column_name from my_table_1 where id = (select max(id) from my_table_2);
The Difference is related to the number of rows returned. If you have only one row returned from nested sql you may prefer both = or in operators. But if multiple rows returned from nested query, use in operator.
So, in your sql example you may prefer using any of the operators. Since, max functions returns only one row.
As you are fetching maximum value from subquery to compare with id, Both(= and IN )will work fine. But If you are trying to fetch more than one row then you have to use IN keyword.
If you have 1 result in sub query you are fine with using = sign, except when data type is wrong, for example , checking with same data type of dummy VARCHAR2(1)
select * from dual where 'X' = (select max(dual.dummy) from dual);
Is similar to using in (also same explain plain)
select * from dual where 'X' in (select max(dual.dummy) from dual);
But checking with different/wrong data type will result with exception ORA-01722 Invalid number
select * from dual where 1 =(select max(dual.dummy) from dual);

How to get result from two queries in same output window?

I need output from the below two queries simultaneously in one output window.
QUERY 1
SELECT C.SERVICENAME, C.SERVICEID , B.SOAPIN, B.SOAPOUT, A.TIMESTAMP
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_SOAPREQUESTS B, Schema1.CFG_SOAPSERVICES C
WHERE B.SERVICEID =C.SERVICEID AND
C.SERVICENAME <>'UploadAndPrepareDocumentEx1__sdweb_services_preload' AND
A.ID=B.LOGENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('02/01/2018 11:55:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('02/01/2018 12:03:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CGBXGVSG')));
Query 2
SELECT B.JSONIN, B.JSONOUT, A.TIMESTAMP, B.EVENT_MESSAGE, A.PROCESSID, A.status, A.SERVERNAME
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_EVENT B
WHERE B.EVENT_MESSAGE NOT IN ('getFileImage','submitBase64','loadDocumentToSign','getRefData') AND
A.ID=B.LOG_ENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('31/12/2017 13:43:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('31/12/2017 13:53:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CTHX8Y2G')));
Run with F5 - you'll get both queries' output in the script panel.
I talk about how this differs here
UNION might be one option, but you'll have to
uniform both column lists (i.e. they have to return the same number of columns which have to be of the same data type), which means that you'd have to add certain NULL columns to both queries
include additional identifier so that you'd know which SELECT returned which values
If you wanted to have them side-by-side, huh, that's not that easy. Thinking loudly: you'd have to have a column that joins those values. Those SELECTs would be inline views. You'd use an aggregate function (such as MAX) along with a DECODE (or CASE) to select values from both queries. Shortly: too much pain.
Now, why do you want to do that? What's wrong with two separate windows, placed side by side?
[EDIT] Showing example of how UNION might look like
select c.servicename, c.serviceid, b.soapin, b.soapout, a.timestamp, to_char(null), to_char(null), to_char(null) , to_number(null), to_char(null), to_char(null)
from ... the rest of your 1st query
union
select null , null , null , null , a.timestamp, b.jsonin , b.jsonout , b.event_message, a.processid , a.status , a.servername
from ... the rest of your 2nd query

How to get dummy rows using SQL Query?

I have a requirement where i have to fetch some rows based on a condition and apart from that 2 more rows should be there in output one will be * and other will be a blank row. I am using the approach of Union to club that 2 extra rows.
Query :
SELECT '' as PROMO_GRP_CD , '' as PROMO_GRP_DESC, '' as PROMO_GRP_ALT_DESC
from PROMO_GROUP
UNION
SELECT '*' as PROMO_GRP_CD , 'All' as PROMO_GRP_DESC, 'Tous' as PROMO_GRP_ALT_DESC
from PROMO_GROUP
UNION
SELECT PROMO_GRP_CD,PROMO_GRP_DESC,PROMO_GRP_ALT_DESC from PROMO_GROUP
where ACC_TYPE = '*' and ACC_SUB_TYPE = '*' and SUBMARKET = '*'
In above Query first 2 selects from Table PROMO_GROUP gives me a blank row and a row with * value and below that i have normal select to retrieve data from Table PROMO_GROUP based on condition.
Is there any other optimum way through which i can achieve this ?
If you want to do it in query only, this is the best way. You should remove the from promo_group part from first two queries
But if you can, you should handle this in your code instead of your query
You need to create each dummy row using a SELECT clause that has no FROM clause (or in Oracle, from the special DUAL table, so it produces exactly one row), and UNION those two with the actual query. Like this:
SELECT '' as PROMO_GRP_CD , '' as PROMO_GRP_DESC, '' as PROMO_GRP_ALT_DESC FROM DUAL
UNION
SELECT '*' as PROMO_GRP_CD , 'All' as PROMO_GRP_DESC, 'Tous' as PROMO_GRP_ALT_DESC FROM DUAL
UNION
SELECT PROMO_GRP_CD,PROMO_GRP_DESC,PROMO_GRP_ALT_DESC from PROMO_GROUP
WHERE ACC_TYPE = '*' and ACC_SUB_TYPE = '*' and SUBMARKET = '*'
You can append the returned result with your two records (adding two element to the array). The result will be the same and you won't have the overhead of the UNION.
Of course you didn't specify what language you are using to run the query through. I am presuming your language will allow this.

Oracle: Order by Union returning ORA-00933: SQL command not properly ended

I have an issue with using Oracle's union and order by clauses together.
I have two complex queries (with sub queries in them) having an order by clause for each of them. I need to union the output of both and return the result. When I run it, I am getting the error ORA-00933: SQL command not properly ended.
But it works when I comment out the order by clauses in both of them.
To test this, I created a simple query as simple as shown below
select * from employee where employee_id=2 order by name
union
select * from employee where employee_id=3 order by name;
Even this gave the same error when ran with order by clauses but runs well when I commentout the order by clauses.
I tried searching forums, but I could not get solution for the exact problem. I found one at ORACLE Query with ORDER BY and UNION but As my queries are already too complecated because of subqueries and joins between too many tables, I dont want to implement this.
Can someone help me on fixing the root cause of the issue.
try this code:
select e1.name name /* e1.* */
from employee e1
where employee_id = 2
union
select
e2.name name /* e2.* */
from employee e2
where employee_id = 3
order by name;
if you want to order the result of first query then to order the result the second query so you can do like this:
select 1 query, e1.name name /* e1.* */
from employee e1
where employee_id = 2
union
select
2 query, e2.name name /* e2.* */
from employee e2
where employee_id = 3
order by query, name;
You can have only one ORDER BY when combining multiple queries, on the last statement. The ORDER BY clause acts on the entire set.
See the Oracle Documentation:
You cannot specify the order_by_clause in the subquery of these operators.
If you want order by in each query you must wrap it in other select as a subquery:
select * from (select * from employee where employee_id=2 order by name)
union
select * from (select * from employee where employee_id=3 order by name);

Resources