AS ____ not working in "Union select statement" - sql

I have this:
SELECT
COUNT(resurs_id) AS 'antalLikes'
FROM kopplaResursLikesUsers
WHERE resurs_id = 19
UNION
SELECT user_id AS 'gillarJagEller'
FROM kopplaResursLikesUsers
WHERE user_id = 5
And I thought the output would be:
antalLikes = 2
gillarJagEller = 5
but the result I get is:
antalLikes[0] = 2
antalLikes[1] = 5
Any ideas why it completely ignores my 2nd "AS" statement?

UNION does make an UNION for COLUMS, not for rows
So, it's taking the first select, get the column 'antalLikes'
and then make the union by the ordinal order.
So, it put the values from your 'gillarJagEller' column in the first one
to get your desired result, I suggest this:
select
(
SELECT
COUNT(resurs_id)
FROM kopplaResursLikesUsers
WHERE resurs_id = 19) AS 'antalLikes',
(
SELECT user_id
FROM kopplaResursLikesUsers
WHERE user_id = 5) AS 'gillarJagEller'

UNION takes as column names only the names specified in the first select statement, in this case, "antalLikes".
To get this:
antalLikes = 2 gillarJagEller = 5
You need something like this:
SELECT
COUNT(resurs_id) AS 'antalLikes',
(SELECT top 1 user_id
FROM kopplaResursLikesUsers
WHERE user_id = 5) AS 'gillarJagEller'
FROM kopplaResursLikesUsers
WHERE resurs_id = 19

Column names and column data types in a UNION are provided by the first select statement in the UNION. Any column names in subsequent `select statements are ignored.
Subsequent select statements in the UNION are required to have the same number of columns as the first select statement. Further, each column in each subsequent select statement must have a datatype that is identical to the column with the same ordinal number in the first select statement or is implicitly convertible to that data type.
WRT to nullity, I believe UNION sets the nullity of each column in the final result set by examining the nullity of that same column in each component select statement. Only if that column is non-nullable across each component select statement is the column in the final result set non-nullable.

Related

How to get "short circuit" in sql query?

I am meeting a database query demand like this:
If there is a record in which the column of 'type' is '1', then return the record.
select * from table where type = 1;
# if the result is not empty, then return it
Otherwise,
return the record in which the 'type' is '2'
select * from table where type = 2;
# even the result is empty
So, how can I merge the two queries into only one, like short circuit:
select * from table where type = 1 (short-circuit-or) type = 2;
# when 'type = 1' matches records, it will not execute 'type = 2'; otherwise, it does like 'union' action.
I will explain why I ask such question. Indeed, the first 3 answers are correct but not 'good' enough. I expect the time consumption is good as query of 'type = 1'. But union and in (1, 2) will cause the DBMS to query type = 2, which will slow the speed even type = 1 matches record.
In Oracle you can try:
SELECT *
FROM table
WHERE type IN (1, 2)
ORDER BY type
FETCH FIRST 1 ROWS ONLY;
In MySQL:
SELECT *
FROM table
WHERE type IN (1, 2)
ORDER BY type
LIMIT 1;
The idea is to get the rows, order them by some criteria and get the first one only.
hope this helps:
SELECT * FROM table WHERE type = 1
UNION
SELECT * FROM table WHERE type = 2 AND NOT EXISTS (SELECT * FROM table WHERE type = 1);
This will return all rows where type=1 and then append all rows where type=2 if and only if there are no rows where type=1.
Edited : I think this approach may be faster
SELECT *
FROM table
WHERE type IN (1, 2)
ORDER BY CASE WHEN type = 1 THEN 0 ELSE 1 END;
This query will return the first record that matches either type = 1 or type = 2, but it will prioritize records where type = 1 by ordering them before records where type = 2.
You can use the SQL UNION operator to combine the results of two SELECT statements into a single result set. Here is an example query that meets your requirement:
SELECT * FROM table WHERE type = 1
UNION ALL
SELECT * FROM table WHERE type = 2 AND NOT EXISTS (SELECT * FROM table WHERE type = 1);
This query first selects all records with type = 1. If this query returns any rows, they are returned as the result.
If the first query returns no rows, the second query is executed. This second query selects all records with type = 2 that do not have a corresponding row with type = 1. The NOT EXISTS clause ensures that only records with type = 2 that were not returned by the first query are included in the result.
By using UNION ALL, duplicates are not removed from the result set, which means that if a record has type = 1 and type = 2, it will be returned twice in the result set. If you want to remove duplicates, you can use just UNION instead of UNION ALL.

Column Mismatch in UNION queries

I have columns A,B in Table 1 and columns B,C in Table 2.Need to perform Union between them .
For example : select A,B from Table 1 UNION select 0,B from Table 2.
I dont need this zero to solve the column mismatch.Instead is there any other solution?
Am asking the question by providing simple example . But in my case the table structure is very large and the queries are already built.Now I need to fix this union query by replacing this zero.(due to DB2 upgrade)
Can anyone help?
For two legs A and B in a union to be union compatible it is required that:
a) A and B have the same number of columns
b) The types for each column in A is compatible with the corresponding column in B
In your query you can use null that is part of every type:
select a, b from T1
UNION
select null, b from T2
Under certain circumstances, you may have to explicitly cast null to the same type as A has (probably not in this case):
select a, b from Table 1
UNION
select cast(null as ...), b from Table 2
A column returned in a SQL result set can only have one data type.
A union or union all results in rows from the first query and the rows of the second query (in case of union they are deduplicated).
So the first column of the first query needs to match the data type of the first column of the second query.
You can check this by running a describe:
describe select a,b from t1
If you work within a GUI (JDBC Connection) you could also use
call admin_cmd('describe select a,b from t1')
So if the some column does not match you have to explicitly cast the data types.

Display default value if query results in no records in BigQuery

A query can return an empty table on BigQuery. An example of such occurrence is if I join a bunch of tables in a query on BigQuery and the result of the joins is an empty table, or if there are no matches based on the where clause.
Here is a dumb sample query that will always return in an empty join:
#standardSQL
WITH query1 AS (
SELECT 1 AS number, "one" AS message
), query2 AS (
SELECT 2 AS number, "two" AS message)
SELECT "query result" AS result, query1.*
FROM query1
JOIN query2 ON query1.number = query2.number;
The query will show this output: Query returned zero records.
If that's the case I want to return either a message or a default row. But I don't know how to do that. I've tried using IFNULL, but that's only usuable for one column, not number of columns. Using an IF statement gave me errors as you can't return row(s) from an if statement.
I think the error it gave me was Scalar subquery cannot have more than one column unless using SELECT AS STRUCT to build STRUCT values.
Another thing that I could think of, but don't know how to implement is to add a UNION at the end that would only trigger if the previous parts didn't return anything. Or wrap the existing query in a WITH statement subquery and if that returns nothing, print a message, else do SELECT * FROM sub_query.
I'd like to either just display a message when an empty table is the result, or return a row with some default values.
I understand the answer is likely to contain a UNION statement and hence displaying just a message won't be possible. In that case I'd like to display a default row instead. For the above sample query a default row would look like: "No results found", NULL, NULL.
When the query returns a non empty table, I want it to look exactly like it did with the original query. So there shouldn't be any added columns or change to the schema of the result.
You would use union all. Something like this:
with t as (
. . . <all your query stuff here>
)
select cast(NULL as string) as msg, t.*
from t
union all
select msg, t.* -- all the `t` columns will be `NULL`
from (select 'No rows returned' as msg) left join
t
on 1 = 0 -- always false
where not exists (select 1 from t);
Note the complications. A query returns a fixed set of columns with a fixed set of names. This version returns an extra column at the beginning of the data to contain the message. In order to get all the rest of the columns, a left join is used, but the on clause is always false.
Option 1
Below displays row with all nulls in case if there is no result returned for your_query
#standardSQL
WITH your_query AS ( ... )
SELECT * FROM your_query
UNION ALL
SELECT your_query.* REPLACE ("No results found" AS result)
FROM (SELECT 1)
LEFT JOIN your_query ON FALSE
WHERE NOT EXISTS (SELECT 1 FROM your_query)
Row result number message
1 No results found null null
Option 2
If you know in advance output schema - below returns default row (assuming 0 default for number and "none" default for message
#standardSQL
WITH your_query AS ( ... )
SELECT * FROM your_query
UNION ALL
SELECT "No results found", 0, "none" FROM (SELECT 1)
LEFT JOIN your_query ON FALSE
WHERE NOT EXISTS (SELECT 1 FROM your_query)
Row result number message
1 No results found 0 none

How do I select only 1 row in sybase without using rowcount

How do I select only 1 row in sybase without using rowcount? I don't have the privilege to set rowcount in sybase. Is there a way to select only 1 row?
For example:
select * from table where name = 'jack'
This returns two rows; how do I select only one row from the result set without using set rowcount?
Try the query:
SELECT TOP 1 * FROM mytable
WHERE name = 'jack'
As you might guess, this selects the TOP 1 matching results. If you wanted more (which you don't here) you could use any number (TOP 100 or TOP 1000, etc).
A more comprehensive example can be found on w3schools: http://www.w3schools.com/Sql/sql_top.asp
There seems to be a reason, why you're getting more than 1 row for "WHERE name = 'jack'", it looks as if the rows differ.
But if, the rows do not differ you can try adding "distinct":
SELECT DISTINCT * FROM TABLE WHERE name = 'jack'
or try with "GROUP BY" statement, then you should type explicitly all columns, eg.:
SELECT name FROM TABLE WHERE name = 'jack' GROUP BY name
if this is not what you wanted, can you paste here how the 2 rows look exactly?
If you want a single result, use 'GROUP BY' and 'HAVING column = max(column)'. Or replace max() with min().
This should work unless the max or min values are also not unique.

Optionally use a UNION from another table in T-SQL without using temporary tables or dynamic sql?

I have two sql server tables with the same structure. In a stored procedure I have a Select from the first table. Occasionally I want to select from the second table as well based on a passed in parameter.
I would like a way to do this without resorting to using dynamic sql or temporary tables.
Pass in param = 1 to union, anything else to only return the first result set:
select field1, field2, ... from table1 where cond
union
select field1, field2, ... from table2 where cond AND param = 1
If they are both the exact same structure, then why not have a single table with a parameter that differentiates the two tables? At that point, it becomes a simple matter of a case statement on the parameter on which results set you receive back.
A second alternative is dual result sets. You can select multiple result sets out of a stored procedure. Then in code, you would either use DataReader.NextResult or DataSet.Tables(1) to get at the second set of data. It will then be your code's responsibility to place them into the same collection or merge the two tables.
A THIRD possibility is to utilize an IF Statement. Say, pass in an integer with the expected possible values of 1,2, 3 and then have something along this in your actual stored procedure code
if #Param = 1 Then
Select From Table1
if #Param = 2 THEN
Select From Table2
if #Param = 3 Then
Select From Table1 Union Select From Table 2
A fourth possibility would be to have two distinct procedures one which runs a union and one which doesn't and then make it your code's responsibility to determine which one to call based on that parameter, something like:
myCommandObject.CommandText = IIf(myParamVariable = true, "StoredProc1", StoredProc2")
It's pretty easy.
/* Always return tableX */
select colA, colB
from tableX
union
select colA, colB
from tableY
where #parameter = 'IncludeTableY' /* Will union with an empty set otherwise */
If this isn't immediately apparent (it often isn't), consider the examples below. The primary thing to remember is that the if the where clause evaluates to true for a row, it is returned otherwise it's discarded.
This always evaluates to true so every row is returned.
select *
from tableX
where 1 = 1
This always evaluates to false so no rows are returned (sometimes used as a quick and dirty get-me-the-columns query).
select *
from tableX
where 1 = 0
this will return values from either table, depending on if you passed a value on the parameter
select field1, field2, ... from table1 where #p1 is null
union
select field1, field2, ... from table2 where #p1 is not null
you just need to add the rest of your criteria for the where clause
Use a view.
CREATE view_both
AS
SELECT *, 1 AS source
FROM table1
UNION ALL
SELECT *, 2 AS source
FROM table2
SELECT * FROM view_both WHERE source < #source_flag
The optimizer determines which, or both, tables to use based on source without requiring it to be indexed.