How to limit the columns of the select statement? - sql

I have to create a new table and inside should be the columns I get from the CASE statement. I do not need the rest of the columns resulting from the select statement
for example:
CREATE TABLE test
AS (
SELECT a.id, ...
CASE WHEN a.id = 1 THEN 2
ELSE 0
END as LegalType
FROM table a, ...
WHERE ...);
now my question how can I select only the column LegalType from the CASE statement? I do not want to have column a.id

You can SELECT INTO
SELECT CASE WHEN a.id = 1 THEN 2 ELSE 0 END as LegalType
....
INTO test
FROM table a
WHERE 1=1);
This will create you a table based on the data returned in the SELECT. see https://msdn.microsoft.com/en-GB/library/ms188029.aspx

Related

Create and use column in create statement same time of table

I want to create a table with fetch the data from source table.
I can do it using alter and update function but I don't want to do it that way.
I have to create two columns and use 1 column(c1) in other as case statement in second(c2) column.
insert into table t
(select
a,b, case when d>f then 1 else 0 end as c1,
case when c1=1 then "yes" else null end as c2,
from base_temp
where a>b
)
If the question is on how to create a table and populate it with the results of some SELECT statement, then look at the CREATE TABLE as-result-table syntax.
You may use AS (full-select) WITH DATA syntax to create a new table with metadata based on the query provided and insert the result of this query into this table at the same time.
If the question is on how to use column aliases in expressions, then refer to the Expressions refer to column aliases topic.
You must have the SQL_COMPAT global variable set to the 'NPS' value in your session to make it work.
You may set it with the SET SQL_COMPAT = 'NPS' statement before running the corresponding SELECT statement.
SET SQL_COMPAT='NPS';
SELECT
TABSCHEMA, TABNAME
, CASE WHEN COLCOUNT > 20 THEN 1 ELSE 0 END AS C1
, CASE WHEN C1 = 1 THEN 'YES' ELSE NULL END AS C2
FROM SYSCAT.TABLES
FETCH FIRST 5 ROWS ONLY;
If you can't or don't want to set this variable, you may use sub-select to achieve the same:
SELECT
TABSCHEMA, TABNAME
, C1
, CASE WHEN C1 = 1 THEN 'YES' ELSE NULL END AS C2
FROM
(
SELECT
TABSCHEMA, TABNAME
, CASE WHEN COLCOUNT > 20 THEN 1 ELSE 0 END AS C1
FROM SYSCAT.TABLES
FETCH FIRST 5 ROWS ONLY
);

Compare each row values in second table in SQL Server?

I have a scenario where I have to search value of column 1 in first table to see whether it matches some value in another table.
This should continue in a loop until the last row on first table has been compared.
No loops needed. You can do this easily as a set based operation using exists()
select *
from FirstTable
where exists (
select 1
from SecondTable
where FirstTable.Column1 = SecondTable.Column1
);
To find the opposite, where the row in the first table does not have a match based on Column1, you can use not exists()
select *
from FirstTable
where not exists (
select 1
from SecondTable
where FirstTable.Column1 = SecondTable.Column1
);
If you want to identify which rows have a match and don't you can use:
select FirstTable.*
, MatchFound = case when x.Column1 is null then 'No' else 'Yes' end
, x.Column1
from FirstTable
outer apply (
select top 1
*
from SecondTable
where FirstTable.Column1 = SecondTable.Column1
) as x

Filter if values provided otherwise return everything

Say I have a table t with 2 columns:
a int
b int
I can do a query such as:
select b
from t
where b > a
and a in(1,2,3)
order by b
where 1,2,3 is provided from the outside.
Obviously, the query can return no rows. In that case, I'd like to select everything as if the query did not have the and a in(1,2,3) part. That is, I'd like:
if exists (
select b
from t
where b > a
and a in(1,2,3)
)
select b
from t
where b > a
and a in(1,2,3)
order by b
else
select b
from t
where b > a
order by b
Is there a way to do this:
Without running two queries (one for exists, the other one the actual query)
That is less verbose than repeating queries (real queries are quite long, so DRY and all that stuff)
Using NOT EXISTS with a Sub Query to Determine if condition exists
SELECT b
FROM
t
WHERE
b > a
AND (
NOT EXISTS (SELECT 1 FROM #Table WHERE a IN (1,2,3))
OR a IN (1,2,3)
)
ORDER BY
b
The reason this works is because if the condition exists then the OR statement will include the rows and if the condition does not exist then the NOT EXISTS will include ALL rows.
Or With Common Table Expression and window Function with Conditional Aggregation.
WITH cte AS (
SELECT
b
,CASE WHEN a IN (1,2,3) THEN 1 ELSE 0 END as MeetsCondition
,COUNT(CASE WHEN a IN (1,2,3) THEN a END) OVER () as ConditionCount
FROM
t
)
SELECT
b
FROM
cte
WHERE
(ConditionCount > 0 AND MeetsCondition = 1)
OR (ConditionCount = 0)
ORDER BY
b
I find it a bit "ugly". Maybe it would be better to materialize output from your query within a temp table and then based on count from temp table perform first or second query (this limits accessing the original table from 3 times to 2 and you will be able to add some flag for qualifying rows for your condition not to repeat it). Other than that, read below . . .
Though, bear in mind that EXISTS query should execute pretty fast. It stops whether it finds any row that satisfies the condition.
You could achieve this using UNION ALL to combine resultset from constrained query and full query without constraint on a column and then decide what to show depending on output from first query using CASE statement.
How CASE statement works: when any row from constrained part of your query is found, return resultset from constrainted query else return everything omitting the constraint.
If your database supports using CTE use this solution:
with tmp_data as (
select *
from (
select 'constraint' as type, b
from t
where b > a
and a in (1,2,3) -- here goes your constraint
union all
select 'full query' as type, b
from t
where b > a
) foo
)
SELECT b
FROM tmp_data
WHERE
CASE WHEN (select count(*) from tmp_data where type = 'constraint') > 0
THEN type = 'constraint'
ELSE type = 'full query'
END
;

How can I group by two rows in SQL?

In the result of an SQL Select command I have two rows:
A | B
B | A
A|B and B|A means the same to me. I want, that only one of them would be selected in an SQL command.
How can I do that?
I have a select command , I join it self (natural join), like this:
SELECT a.coloumn ,b.coloumn
FROM table a,table b
where .... (not important)
and b.coloumn IN (
SELECT coloumn
FROM table
where ... (the same like above)
)
and b.coloumn != a.coloumn ;
And after that I have multiple coloumns.
You neither told us your column names nor your table name, but assuming you have two columns A and B in a table named the_table then the following will do:
select distinct least(a,b), greatest(a,b)
from the_table;
If you want to group by them using standard SQL:
select (case when a < b then a else b end) as a,
(case when a < b then b else a end) as b,
count(*) as cnt
from table t
group by (case when a < b then a else b end),
(case when a < b then b else a end);
Oracle supports the greatest() and least() functions, but not all databases do.
Another possible solution is:
select a, b from the_table
union
select b, a from the_table
This would work fine even if there are NULL values.

Referring to results of a sub query in main query

I have a sub query that returns one column, showing as GroupType, I then want to do a CASE function on this result within the main query, however I get an invalid column name when using the CASE statement.
Can i do this in SQL to do I have to refer to it by a different name
SELECT CASE
WHEN
(
SELECT column
FROM othertable
) = 1
THEN '1'
ELSE '2'
END
FROM mytable
To reuse the subquery result:
SELECT subvalue, CASE subvalue WHEN 1 THEN 1 ELSE 2 END
FROM (
SELECT (
SELECT column
FROM othertable
) AS subvalue
FROM mytable
) q