Merge two SQL queries - sql

How to combine two SQL queries in one?
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23

This is one way
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
UNION ALL
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23
but you should get into the habit of explicitly listing columns. The columns must align or it won't work.
Here's another way
SELECT * FROM table1
WHERE (chapter=88 AND sentence>=23) OR (chapter=89 AND sentence>=1 AND sentence<=23)

You can join the queries like this:
SELECT * FROM table1
WHERE
(chapter = 88 AND sentence >= 23)
OR
(chapter = 89 AND sentence >= 1 AND sentence <= 23)

SELECT *
FROM TABLE1
WHERE ( CHAPTER = 88
AND SENTENCE >= 23 )
OR ( CHAPTER = 89
AND SENTENCE >= 1
AND SENTENCE <= 23 )

Try this:
SELECT *
FROM TABLE1
WHERE ( CHAPTER = 88
AND SENTENCE >= 23 )
OR ( CHAPTER = 89
AND SENTENCE BETWEEN 1 AND 23 );

You've two ways to do it with a table like this and some sample data
create table table1 (id number, chapter number, sentence number);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (1,65,24);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (2,22,22);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (3,88,25);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (4,89,15);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (4,89,33);
You can use a union to munge the two sets together
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
UNION
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23;
or merge the predicates in the where clause to achieve the same thing
SELECT *FROM table1 WHERE (chapter=88 AND sentence>=23) or
(chapter=89 AND sentence>=1 AND sentence<=23);
both will give this result
| ID| CHAPTER| SENTENCE|
----------------------------------
| 3| 88| 25|
| 4| 89| 15|

Try this:
SELECT * FROM table1
WHERE (chapter=88 and sentence>=23)
OR (chapter=89 and sentence>=1 and sentence<=23)
This should return the results from both queries.

SELECT *
FROM table1
WHERE (chapter = 88 AND sentence >= 23)
OR (chapter = 89 AND sentence >= 1 AND sentence <= 23)

Select *
From table1
where ((chapter=88 AND sentence>=23)
OR (chapter=89 AND sentence>=1 AND sentence<=23));
Also, you can use the BETWEEN keyword in the second clause.

You don't need any Union or Merge statement those operations are redundant. Just change the conditions of your first select.
SELECT *FROM table1 WHERE (chapter=88 OR chapter=89) AND
sentence>= (CASE WHEN chapter = 88
THEN 23
WHEN chapter = 89
THEN 1
END ) AND
sentence <= (CASE WHEN chapter = 89
THEN 23
ELSE sentence
END)

SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
UNION
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23

Related

Return five rows of random DNA instead of just one

This is the code I have to create a string of DNA:
prepare dna_length(int) as
with t1 as (
select chr(65) as s
union select chr(67)
union select chr(71)
union select chr(84) )
, t2 as ( select s, row_number() over() as rn from t1)
, t3 as ( select generate_series(1,$1) as i, round(random() * 4 + 0.5) as rn )
, t4 as ( select t2.s from t2 join t3 on (t2.rn=t3.rn))
select array_to_string(array(select s from t4),'') as dna;
execute dna_length(20);
I am trying to figure out how to re-write this to give a table of 5 rows of strings of DNA of length 20 each, instead of just one row. This is for PostgreSQL.
I tried:
CREATE TABLE dna_table(g int, dna text);
INSERT INTO dna_table (1, execute dna_length(20));
But this does not seem to work. I am an absolute beginner. How to do this properly?
PREPARE creates a prepared statement that can be used "as is". If your prepared statement returns one string then you can only get one string. You can't use it in other operations like insert, e.g.
In your case you may create a function:
create or replace function dna_length(int) returns text as
$$
with t1 as (
select chr(65) as s
union
select chr(67)
union
select chr(71)
union
select chr(84))
, t2 as (select s,
row_number() over () as rn
from t1)
, t3 as (select generate_series(1, $1) as i,
round(random() * 4 + 0.5) as rn)
, t4 as (select t2.s
from t2
join t3 on (t2.rn = t3.rn))
select array_to_string(array(select s from t4), '') as dna
$$ language sql;
And use it in a way like this:
insert into dna_table(g, dna) select generate_series(1,5), dna_length(20)
From the official doc:
PREPARE creates a prepared statement. A prepared statement is a server-side object that can be used to optimize performance. When the PREPARE statement is executed, the specified statement is parsed, analyzed, and rewritten. When an EXECUTE command is subsequently issued, the prepared statement is planned and executed. This division of labor avoids repetitive parse analysis work, while allowing the execution plan to depend on the specific parameter values supplied.
About functions.
This can be much simpler and faster:
SELECT string_agg(CASE ceil(random() * 4)
WHEN 1 THEN 'A'
WHEN 2 THEN 'C'
WHEN 3 THEN 'T'
WHEN 4 THEN 'G'
END, '') AS dna
FROM generate_series(1,100) g -- 100 = 5 rows * 20 nucleotides
GROUP BY g%5;
random() produces random value in the range 0.0 <= x < 1.0. Multiply by 4 and take the mathematical ceiling with ceil() (cheaper than round()), and you get a random distribution of the numbers 1-4. Convert to ACTG, and aggregate with GROUP BY g%5 - % being the modulo operator.
About string_agg():
Concatenate multiple result rows of one column into one, group by another column
As prepared statement, taking
$1 ... the number of rows
$2 ... the number of nucleotides per row
PREPARE dna_length(int, int) AS
SELECT string_agg(CASE ceil(random() * 4)
WHEN 1 THEN 'A'
WHEN 2 THEN 'C'
WHEN 3 THEN 'T'
WHEN 4 THEN 'G'
END, '') AS dna
FROM generate_series(1, $1 * $2) g
GROUP BY g%$1;
Call:
EXECUTE dna_length(5,20);
Result:
| dna |
| :------------------- |
| ATCTTCGACACGTCGGTACC |
| GTGGCTGCAGATGAACAGAG |
| ACAGCTTAAAACACTAAGCA |
| TCCGGACCTCTCGACCTTGA |
| CGTGCGGAGTACCCTAATTA |
db<>fiddle here
If you need it a lot, consider a function instead. See:
What is the difference between a prepared statement and a SQL or PL/pgSQL function, in terms of their purposes?

SQL Server - How to check if a value does not exist in other rows of the same table for same column values?

Following are the two tables in SQL Server: TABLE_A and TABLE_B
I need to get the output as follows:
Get IDs from TABLE_A where Exist = 0
We would get 100, 101 & 102
Now, among 100, 101 & 102, no other rows (in the same table) with the same ID value should have Exist = 1
Hence, 100 can't be selected as it has Exist = 1 in the 2nd row.
So, only 101 & 102 remain
With the remaining ID values (101 & 102), check against the ID column in TABLE_B where 'Exist' column value should not be equal to '1' in any of the rows
In TABLE_B, 4th row has Exist = 1 for 102. So, that can't be selected
We have only 101 now. This is required output and that should be selected.
Could you let me know how to write the simplest query to achieve this please? Let me know if the question needs to be improved.
You can use exists & not exists :
with t as (
select t1.*
from t1
where exists (select 1 from t1 t11 where t11.id = t1.id and t11.exists = 0) and
not exists (select 1 from t1 t11 where t11.id = t1.id and t11.exists = 1)
)
select t.*
from t
where not exists (select 1 from t2 where t.id = t2.id and t2.exists = 1);
Try:
SELECT
ID,
SUM(CAST(Exist AS int)) AS [Exists]
FROM
TABLE_A
GROUP BY ID
HAVING SUM(CAST(Exist AS bit)) = 0
will give you the answer to the first part. You can then JOIN this to a similar query for TABLE_B. That is a "simple" way to show how this works. You can write more complex queries as that from #Yogest Sharma
Like #Peter Smith mentioned, you can use the aggregate function SUM. Note that you would need a cast since you cannot use the aggregate function on a field that has a BIT datatype
;WITH CTE AS
(
SELECT ID, SUM(CAST(Exist AS INT)) AS AggExist FROM TABLE_A GROUP BY ID
UNION
SELECT ID, SUM(CAST(Exist AS INT)) As AggExist FROM TABLE_B GROUP BY ID
)
SELECT ID, SUM(AggExist) FROM CTE GROUP BY ID
HAVING SUM(AggExist) = 0
Here is the demo

SQL - Return a default value when my search returns no results along with search criteria

I am searching with a query
--Code Format
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3);
If MYTABLE does not contain rows with SWITCH 1,2 or 3 I need default values returned along with the SWITCH value. How do I do it?
Below is my table format
COLA | COLB | COLC | SWITCH
------------------------------
A B C 1
a b c 2
i want a query when I search with
select * from MYTABLE where switch in (1,2,3)
That gets results like this --
COLA | COLB | COLC | SWITCH
------------------------------
A B C 1
a b c 2
NA NA NA 3
--Check to see if any row exists matching your conditions
IF NOT EXISTS (SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3))
BEGIN
--Select your default values
END
ELSE
BEGIN
--Found rows, return them
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3)
END
if not exists( SELECT 1 from MYTABLE where SWITCH IN (1,2,3))
select default_value
How about:
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3)
union select 5555, 6666, 7777 where not exists (
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3)
);
5555, 6666, 7777 being the default row in case there aren't any rows matching your criteria.
Here is one way to tackle this. You need a table of the SWITCH values you want to look at. Then a simple left join makes this super easy.
select ColA
, ColB
, ColC
v.Switch
from
(
values
(1)
, (2)
, (3)
)v (Switch)
left join YourTable yt on yt.Switch = v.Switch
You can Use a Split Function And Left Join As Shown Below:
Select ISNULL(ColA,'NA') As ColA,ISNULL(ColB,'NA') As ColB,ISNULL(ColC,'NA') As ColC,ISNULL(Switch,a.splitdata)
from [dbo].[fnSplitString]('1,2,3',',') a
LEFT JOIN #MYTABLE t on a.splitdata=t.Switch
[dbo].[fnSplitString] is a Split Function with 2 arguments - Delimeter Separated String and Delimeter and Output a Table.
EDIT:
Given the new explanation, I changed the answer completely. I think I got your question now:
SELECT * FROM MYTABLE AS mt
RIGHT JOIN (SELECT 1 AS s UNION SELECT 2 AS s UNION SELECT 3 AS s) AS st
ON st.s = mt.SWITCH
You could change the SELECT 1 AS s UNION SELECT 2 AS s UNION SELECT 3 AS spart to a subquery that results in all possible values SWITCH could assume. E.g.:
SELECT DISTINCT SWITCH FROM another_table_with_all_switches
If all want is the value of switch that is not in MYTABLE, not the whole table with null values, you could try:
SELECT * FROM
(SELECT 1 AS s UNION SELECT 2 AS s UNION SELECT 3) AS st
WHERE st.s NOT IN (SELECT DISTINCT SWITCH FROM MYTABLE)

add column values of two tables that have the same date

for example, I have 2 tables
resto1
day 1 = 1 2 3 4
resto2
day 1 = 5 6 7 8
I wanted to add the values of the first two columns that have the same date the result would be:
day_1_earned = 6 8 10 12
please help
assuming both the tables have a date column, let say named dt_col you can use below query to achieve the required result
select t1.column1+t2.column2 added_values from
table1 t1,table2 t2
where t1.dt_col = t2.dt_col;
SELECT T1.Column1 + T2.Column As TotalColumn
From T1, T2 WHERE T1.Date= T2.Date
SELECT Cr_date, SUM(Column1) Column1, SUM(Column2) Column2
FROM
(
SELECT Cr_Date,Column1,Column2 FROM #T1
UNION
SELECT Cr_Date,Column1,Column2 FROM #T2
) as res
GROUP BY Cr_Date

How to get result from a column with combined data?

data:
id bb
1 14,35
2 5,11,12,125,36
3 3,23,45,15,1
4 651
5 5,1,6
6 1,7
For example, i wan't get id which with value '1'. So id(3,5,6) should return , but not others with '14' or '11'.
DB: Mysql
This is not the most efficient solution but it might give you what you want off the table:
select id from MyTable where bb like '%,1,%' union
select id from MyTable where bb like '1,%' union
select id from MyTable where bb like '%,1' union
select id from MyTable where bb like '1'
cheers
select * from test where find_in_set('1',bbb)
or
select * from test where bbb REGEXP '(^|,)1(,|$)'
Am I missing something?
SELECT *
FROM MyTable
WHERE (id = 3) or (id = 5) or (id = 6)
you can do like this
select * from mytable where id like '14%' or '11%'