SQL Server, View using multiple select statements - sql

I've banging my head for hours, it seems simple enough, but here goes:
I'd like to create a view using multiple select statements that outputs a Single record-set
Example:
CREATE VIEW dbo.TestDB
AS
SELECT X AS 'First'
FROM The_Table
WHERE The_Value = 'y'
SELECT X AS 'Second'
FROM The_Table
WHERE The_Value = 'z'
i wanted to output the following recordset:
Column_1 | Column_2
'First' 'Second'
any help would be greatly appreciated!
-Thanks.

A union might be what you want, but keep in mind you need to have the exact same columns so you would need to add a null column to each select.
SELECT X AS 'First', Null as 'Second'
FROM The_Table
WHERE The_Value = 'y'
Union
SELECT null as 'First', X AS 'Second'
FROM The_Table
WHERE The_Value = 'z'
This will combine the two results and give you only the unique combinations. My guess is that this isn't what you are looking for.
Is there a reason why you can't accomplish this in one query or do some subqueries perhaps? Maybe you can provide a more concrete example.

if you want this:
Column_1 | Column_2
'First' null
null 'Second'
you can use the UNION like suggested in the other answers, but if you really want then on the same row like in your question:
Column_1 | Column_2
'First' 'Second'
try something like this:
CREATE VIEW dbo.TestDB
AS
SELECT
dt.First,dt2.Second
FROM (SELECT
X AS 'First',ROW_NUMBER() OVER(ORDER BY X) AS RowNumber
FROM The_Table
WHERE The_Value = 'y'
) dt
LEFT OUTER JOIN (SELECT
X AS 'Second',ROW_NUMBER() OVER(ORDER BY X) AS RowNumber
FROM The_Table
WHERE The_Value = 'z'
) dt2 ON dt.RowNumber=dt2.RowNumber
go
I'm not sure how to join the tables, no info about PKs or how to join them is given.

Untested
CREATE VIEW dbo.TestDB
AS
SELECT CASE The_Value when 'y' then x else NULL END AS 'First',
CASE The_Value when 'z' then x else NULL END AS 'Second'
FROM The_Table
WHERE The_Value in( 'y','z')

Related

Partial group by

QUERY:
select ws_path from workpaths where
(
(ws_path like '%R_%') or
(ws_path like '%PB_%' ) or
(ws_path like '%ST_%')
)
OUTPUT:
/x/eng/users/ST_3609843_ijti4689_3609843_1601272247
/x/eng/users/ST_3610020_zozt5229_3610020_1601282033
/x/eng/users/ST_3611181_zozt5229_3611181_1601282032
/x/eng/users/ST_3611226_zozt5229_3611226_1601282033
/x/eng/users-random/john/N_3582168_3551186_1601040805
/x/eng/users-random/james/N_3582619_3551186_1601041405
/x/eng/users-random/jimmy/N_3582791_3551186_1601042005
/x/eng/users/R_3606462_3606462_1601251334
/x/eng/users/R_3611775_3612090_1601290909
/x/eng/users/R_3612813_3613016_1601292252
Is there way to group partially by ST_, N_ and R_?
i.e. group by ws_path wont work at the moment for the obvious reason
I need to only look at the last item in the path (split by '/') and then the front part of splitting with '_'
You can use regexp_substr to get the patterns being searched for and then group by the number of such occurrences.
select regexp_substr(ws_path,'\/R_|\/PB_|\/ST_'), count(*)
from workpaths
group by regexp_substr(ws_path,'\/R_|\/PB_|\/ST_')
Regexp is a good solution but can be expensive. A simpler substring might be cheaper and faster:
CREATE TABLE tbl (field1 VARCHAR(100));
INSERT INTO dbo.tbl
( field1 )
VALUES
('/x/eng/users/ST_3609843_ijti4689_3609843_1601272247'),
('/x/eng/users/ST_3610020_zozt5229_3610020_1601282033'),
('/x/eng/users/ST_3611181_zozt5229_3611181_1601282032'),
('/x/eng/users/ST_3611226_zozt5229_3611226_1601282033'),
('/x/eng/users-random/john/N_3582168_3551186_1601040805'),
('/x/eng/users-random/james/N_3582619_3551186_1601041405'),
('/x/eng/users-random/jimmy/N_3582791_3551186_1601042005'),
('/x/eng/users/R_3606462_3606462_1601251334'),
('/x/eng/users/R_3611775_3612090_1601290909'),
('/x/eng/users/R_3612813_3613016_1601292252');
SELECT
COUNT(CASE WHEN field1 LIKE '%/ST_%' THEN 1 ELSE NULL END) AS 'st_count',
COUNT(CASE WHEN field1 LIKE '%/N_%' THEN 1 ELSE NULL END) AS 'n_count',
COUNT(CASE WHEN field1 LIKE '%/R_%' THEN 1 ELSE NULL END) AS 'r_count'
FROM dbo.tbl

How can I acces the output from the first select statement

I have a table Like this
Col1 | Col2
-----------
a | d
b | e
c | a
Now I want to create an statement to get an output like this:
First| Second
-------------------
a | Amsterdamm
b | Berlin
c | Canada
...
So far I have this consturct what is not working
SELECT *
FROM(
SELECT DISTINCT
CASE
when Col1 IS NULL then 'NA'
else Col1
END
FROM Table1
UNION
SELECT DISTINCT
CASE
when Col2 IS NULL then 'NA'
else Col2
END
FROM Table1
) AS First
,
(
SELECT DISTINCT
when First= 'a' then 'Amsterdam'
when First= 'b' then 'Berlin'
when First= 'c' then 'Canada'
) AS Second
;
can you help me with that
Sorry I have to edit my question to be more specific.
Not as familiar with DB2... I'll lookup if it has a concat function in a sec... and it does.
SELECT First, case when first = 'a' then
concat('This is a ',first)
case when first = 'b' then
concat('To Be or not to ',first)
case else
concat('This is a ',first) end as Second
FROM (
SELECT coalesce(col1, 'NA') as First
FROM Table
UNION
SELECT coalesce(col2, 'NA')
FROM table) SRC
WHERE first <> 'NA'
What this does is generate a single inline view called src with a column called first. If col1 or col2 of table are null then it substitutes NA for that value. It then concatenates first and the desired text excluding records with a first value of 'NA'
Or if you just create an inline table with the desired values and join in...
SELECT First, x.b as Second
FROM (
SELECT coalesce(col1, 'NA') as First
FROM Table
UNION
SELECT coalesce(col2, 'NA')
FROM table) SRC
INNER JOIN (select a,b
from (values ('a', 'This is a'),
('b', 'To B or not to' ),
('c', 'I like cat whose name starts with')) as x(a,b)) X;
on X.a = src.first
WHERE first <> 'NA'
Personally I find the 2nd option easier to read. Though if you have meaning for a,b,c I would think you'd want that stored in a table somewhere for additional access. In code seems like a bad place to store data like this that could change.
Assuming you want
a this is a a
b this is a b
c this is a c
d this is a d
e this is a e
thanks to xQbert
I could solve this problem like this
SELECT FirstRow, concat
(
CASE FirstRow
WHEN 'AN' then 'amerstdam'
WHEN 'G' then 'berlin'
ELSE 'NA'
END, ''
) AS SecondRow
FROM(
Select coalesce (Col1, 'NA') as FirstRow
FROM Table1
UNION
Select coalesce (Col2, 'NA')
FROM Table1) SRC
WHERE FirstRow <> 'NA'
;

Can Oracle PL/SQL CASE statement include a SELECT query?

I'm trying to do something similar to this:
CASE
WHEN number IN (1,2,3) THEN 'Y' ELSE 'N' END;
Instead I want to have a query in the place of the list, like so:
CASE
WHEN number IN (SELECT num_val FROM some_table) THEN 'Y' ELSE 'N' END;
I can't seem to get this to work. Also, here is an example of the query.
SELECT number, (CASE
WHEN number IN (SELECT num_val FROM some_table) THEN 'Y' ELSE 'N' END) AS YES_NO
FROM some_other_table;
Yes, it's possible. See an example below that would do what you are intending. The difference is that it uses EXISTS instead of IN.
SELECT a.number,
(CASE WHEN EXISTS (SELECT null FROM some_table b where b.num_val = a.number)
THEN 'Y'
ELSE 'N'
END) AS YES_NO
FROM some_other_table a;
EDIT:
I confess: I like the answers given by the others better personally.
However, there will be a difference between this query and the others depending on your data.
If for a value number in the table some_other_table you can have many matching entries of num_val in the table some_table, then the other answers will return duplicate rows. This query will not.
That said, if you take the left join queries given by the others, and add a group by, then you won't get the duplicates.
I suggest using an OUTER JOIN instead of trying to use a subquery in a CASE expression:
SELECT t.NUMBER,
CASE
WHEN s.NUM_VAL IS NOT NULL THEN 'Y'
ELSE 'N'
END AS YES_NO
FROM SOME_OTHER_TABLE t
LEFT OUTER JOIN SOME_TABLE s
ON s.NUM_VAL = t.NUMBER
Best of luck.
Seems like you just need to join the tables and do a decode.
with x as
(
select 1 as num from dual
union
select 2 as num from dual
union
select 3 as num from dual
),
y as
(
select 1 as num from dual
union
select 2 as num from dual
union
select 4 as num from dual
)
select x.num, decode(y.num, null, 'N','Y') as yes_no
from x
left outer join y on (x.num = y.num)
Output:
NUM YES_NO
1 Y
2 Y
3 N
You can use subquery in case statement:
select
case dummy
when 'X' then (select 'TRUE' from dual)
else 'FALSE'
end TEST
from dual;
TEST
TRUE
select
case (select 'XXX' from dual)
when 'XXX' then 'TRUE'
else 'FALSE'
end TEST
from dual;
TEST
TRUE

How to write query to return value regardless of existance?

Given this:
with data_row as (select 1 as col_1 from dual)
select 'Y' as row_exists from dual where exists
(select null
from data_row
where col_1 in (2,1))
How can I get this?
Col_1 Row_exists
--------------------
1 Y
2 N
In order to get a row of output, you need a row of input. You want to get the second row with a "2", but there is no table with that value.
The approach is to generate a table that has the values that you want, and then use left outer join to find which match:
with data_row as (
select 1 as col_1
from dual
),
what_i_care_about as (
select 1 as col from dual union all
select 2 from dual
)
select wica.col,
(case when dr.col_1 is NULL then 'N' else 'Y' end) as row_exists
from what_i_care_about wica left outer join
data_row dr
on wica.col = dr.col_1;
You cannot do directly what you want -- which is to create a row for each missing value in the in list. If you have a lot of values and they are consecutive numeric, then you can use connect by or a recursive CTE to generate the values.

Oracle - return multiple counts as one query

I have a couple of queries, detailed below. I'd like to be able to run one SQL query which returns both counts, is this possible?
1.
select nvl(count(rowid), 0) from tablename where OPP = 'FOO' and date = 'BAZ';
2.
select nvl(count(rowid), 0) from tablename where OPP = 'BAR' and date = 'BAZ';
I've only found MSSQL specific solutions in my searches so far.
If you need them in a single row:
SELECT
COUNT(CASE OPP WHEN 'FOO' THEN 1 END),
COUNT(CASE OPP WHEN 'BAR' THEN 1 END)
FROM tablename
WHERE OPP IN ('FOO', 'BAR') AND date = 'BAZ'
(The GROUP BY approach by Thilo is a better generic solution anyway.)
Edit: I've removed NVL(). I had forgotten why I never use it.
If the condition really looks like that (same table, only one field different in the groups):
select opp, count(*) from tablename
where date = 'BAZ'
group by opp
having opp in ('FOO', 'BAR');
For arbitrary queries:
select 'A', count(*) from tableA
union all
select 'B', count(*) from tableB
You could use a with statement:
with
count1 as (
select ...
),
count2 as (
select ...
)
select tot1, tot2
from count1, count2