Input to determine how many datasets to pull from - sql

Hopefully this will make sense:
Basically I want the user to input a variable at the start to determine how many datasets they want to compare:
DECLARE #NumberOfRuns INT
SET #NumberOfRuns = (1,2,3.. normally just 2)
After this I will have a query on multiple datasets:
SELECT*
FROM (Dataset 1)
UNION ALL
SELECT*
FROM (Dataset 2)
Is there a way that if the input for #NumberOfRuns = 1 it only runs the first part, and if the input was 2 it would run both?

Which rdbms? sql-server, mysql oracle? etc. For the non-dynamic route one other method is to use temp table
CREATE TABLE #TempTable (
--Columns And DataTypes of Select Statements
)
INSERT INTO #TempTable (columns)
SELECT *
FROM
Dataset 1
IF #NumberOfRuns >= 2
INSERT INTO #TempTable (columns)
SELECT *
FROM
Dataset 2
IF #NumberOfRuns >= 3
INSERT INTO #TempTable (columns)
SELECT *
FROM
Dataset 3
SELECT *
FROM
#TempTable

You can do an IF ... ELSE ... and hard code it into
IF #NumberOfRuns = 1
SELECT * FROM Dataset1
IF #NumberOfRuns = 2
SELECT * FROM Dataset1
UNION ALL
SELECT * FROM Dataset2
IF #NumberOfRuns = 3
SELECT * FROM Dataset1
UNION ALL
SELECT * FROM Dataset2
UNION ALL
SELECT * FROM Dataset3
etc...

In SQL Server you could just write your union ONCE and pull it into a #Temp and then filter on a column you set.
select
1 as ColumnID
....
INTO #Temp
....
UNION ALL
SELECT
2 as ColumnID
....
UNION ALL
SELECT
3 as ColumnID
....
SELECT * FROM #Temp WHERE ColumnID <= #NumberOfRuns

Related

How do i create a DB2 UNION query using variables from a list

So i have a union query like:
select count(id)
from table 1
where membernumber = 'x'
and castnumber = 'y'
union
select count(id)
from table 1
where membernumber = 'x'
and castnumber = 'y'
union
etc...
There will be over 200 unions coming from a list 2x 200 table with values for x and y in each row. So each union query has to get the value of x and y from the corresponding row (not in any particular order).
How can i achieve that ?
Thanks
Try this:
DECLARE GLOBAL TEMPORARY TABLE
SESSION.PARAMETERS
(
MEMBERNUMBER INT
, CASTNUMBER INT
) DEFINITION ONLY WITH REPLACE
ON COMMIT PRESERVE ROWS NOT LOGGED;
-- Insert all the the constants in your application with
INSERT INTO SESSION.PARAMETERS
(MEMBERNUMBER, CASTNUMBER)
VALUES (?, ?);
-- I don't know the meaning of the result you want to get
-- but it's equivalent
select distinct count(t.id)
from table1 t
join session.parameters p
on p.membernumber = t.membernumber
and p.castnumber = t.castnumber
group by t.membernumber, t.castnumber;

SQL: I want a row to be return with NULL even if there is no match to my IN clause

I would like my SQL query to return a row even if there is no row matching in my IN clause.
For exemple this query:
SELECT id, foo
FROM table
WHERE id IN (0, 1, 2, 3)
would return:
id|foo
0|bar
1|bar
2|bar
3|null
But instead I have (because no row with id 3):
id|foo
0|bar
1|bar
2|bar
I have been able to find this trick:
SELECT tmpTable.id, table.bar
FROM (
SELECT 0 as id
UNION SELECT 1
UNION SELECT 2
UNION SELECT 3
) tmpTable
LEFT JOIN
(
SELECT table.foo, table.id
FROM table
WHERE table.id IN (0, 1, 2, 3)
) table
on table.id = tmpTable.id
Is there a better way?
Bonus: How to make it work with myBatis's list variable?
overslacked is right. Most SQL developers use an auxiliary table that stores integers (and one that stores dates). This is outlined in an entire chapter of Joe Celko's "SQL for Smarties".
Example:
CREATE TABLE numeri ( numero INTEGER PRIMARY KEY )
DECLARE #x INTEGER
SET #x = 0
WHILE #x < 1000
BEGIN
INSERT INTO numeri ( numero ) VALUES ( #x )
SET #x = #x + 1
END
SELECT
numero AS id,
foo
FROM
numeri
LEFT OUTER JOIN my_table
ON my_table.id = numero
WHERE
numero BETWEEN 0 AND 3
Main Goal of Programming minimal code high performance no need this things just remove id 3 from in clause
What about just saying:
SELECT id, foo
FROM table
WHERE id >= 0 AND <= 3

Conditional SQL Statement

I would like to ask if it is possible to create a SQL statement with an if or similar structure.
I have two queries and would like to combine them into one. The only difference between the two is that one has additional AND conditions on its WHERE clause.
I tried doing a select case, but was not very successful. I will create a parameter "test" that will take 1 or 2, and that condition should determine which query to run.
Here are the queries...
Query 1
SELECT ID,AVG(B.VOL) AS PVOL
FROM (SELECT VAR1 AS ID, SUM(VOL) AS PVOL FROM table1 WHERE VAR1='xyz'
AND DATE_D>'10/28/2013' AND DATE_D<'10/31/2013'
AND CUSTOMER='Market' AND MARKET='South' AND PROJECT=0
GROUP BY VAR1,DATE_D) B GROUP BY ID
Query 2
SELECT ID,AVG(B.VOL) AS PVOL
FROM (SELECT VAR1 AS ID, SUM(VOL) AS PVOL FROM table1 WHERE VAR1='xyz'
AND DATE_D>'10/28/2013' AND DATE_D<'10/31/2013'
AND PROJECT=0
GROUP BY VAR1,DATE_D) B GROUP BY ID
You could create a sproc that accepts the "test" parameter that you hope to build your IF statement around.
create procedure --sprocname
(
#test int
)
as
begin
set nocount on
if
#test = --bool
select statement 1
else
select statement 2
end
sorry for the poor format I was in a hurry setting it up
You can add the condition based on your parameter #test like below
same query can be used , based on the parameter the condition will be varied.
SELECT ID,AVG(B.VOL) AS PVOL
FROM (SELECT VAR1 AS ID, SUM(VOL) AS PVOL FROM table1 WHERE VAR1='xyz'
AND DATE_D>'10/28/2013' AND DATE_D<'10/31/2013'
AND ( (#test = 1 AND CUSTOMER='Market' AND MARKET='South' AND PROJECT=0 )
OR ( #test =2 AND PROJECT=0 )
)
GROUP BY VAR1,DATE_D) B GROUP BY ID

How to convert list of numbers into (temp) table using SQL (SQL Server)

Here is an example;
I have list of numbers (1,5,8,36) and I want these values as a (temp) table rows. One of the way to do is as follow
select 1 as n into ##temp
union
select 5 as n
union
select 8 as n
union
select 36 as n
The problem is number list is dynamic . it can have any no of values. So I need a proper systematic way to convert these values into temp table rows.
A solution I use alot...
Supply your list of numbers as a VARCHAR(MAX) comma delimeted string, then use one of the many dbo.fn_split() functions that people have written on line.
One of many examples online... SQL-User-Defined-Function-to-Parse-a-Delimited-Str
These functions take a string as a parameter, and return a table.
Then you can do things like...
INSERT INTO #temp SELECT * FROM dbo.split(#myList)
SELECT
*
FROM
myTable
INNER JOIN
dbo.split(#myList) AS list
ON list.id = myTable.id
An alternative is to look into Table Valued Parameters. These allow you to pass a whole table in to a stored procedure as a parameter. How depends on the framework you're using. Are you in .NET, Java, Ruby, etc, and how are you communicating with the database?
Once we know more details about your applicaiton code we can show you both the client code, and the SQL stored procedure template, for using Table Valued Parameters.
You Can Use Below Query For Select 100 Random Value From 1 To 9
Declare #Index Int = 1
Declare #Result Table (Col Int)
While #Index <= 100 Begin
Insert Into #Result (Col)
Select FLOOR( RAND() * 10)
Set #Index = #Index + 1
End
Select * From #Result
I use this for a generic set of numbered rows.
SELECT DISTINCT ORDINAL_POSITION AS NUMBER_VAL
FROM INFORMATION_SCHEMA.COLUMNS
WHERE ORDINAL_POSITION BETWEEN 1 AND 36
ORDER BY ORDINAL_POSITION
create temporary table NS AS (
SELECT a+b+c+d+e+f+g+h
FROM (SELECT 0 as a UNION SELECT 1)
CROSS JOIN (SELECT 0 as b UNION SELECT 2)
CROSS JOIN (SELECT 0 as c UNION SELECT 4)
CROSS JOIN (SELECT 0 as d UNION SELECT 8)
CROSS JOIN (SELECT 0 as e UNION SELECT 16)
CROSS JOIN (SELECT 0 as f UNION SELECT 32)
CROSS JOIN (SELECT 0 as g UNION SELECT 64)
CROSS JOIN (SELECT 0 as h UNION SELECT 128)
WHERE a+b+c+d+e+f+g+h BETWEEN 1 AND 200
ORDER BY 1
)

return a default record from a sql query

I have a sql query that I run against a sql server database eg.
SELECT * FROM MyTable WHERE Id = 2
This may return a number of records or may return none. If it returns none, I would like to alter my sql query to return a default record, is this possible and if so, how? If records are returned, the default record should not be returned. I cannot update the data so will need to alter the sql query for this.
Another way (you would get an empty initial rowset returned);
SELECT * FROM MyTable WHERE Id = 2
IF (##ROWCOUNT = 0)
SELECT ...
SELECT TOP 1 * FROM (
SELECT ID,1 as Flag FROM MyTable WHERE Id = 2
UNION ALL
SELECT 1,2
) qry
ORDER BY qry.Flag ASC
You can have a look to this post. It is similar to what you are asking
Return a value if no rows are found SQL
I hope that it can guide you to the correct path.
if not exists (SELECT top 1 * FROM mytable WHERE id = 2)
select * from mytable where id= 'whatever_the_default_id_is'
else
select * from mytable where id = 2
If you have to return whole rows of data (and not just a single column) and you have to create a single SQL query then do this:
Left join actual table to defaults single-row table
select
coalesce(a.col1, d.col1) as col1,
coalesce(a.col2, d.col2) as col2,
...
from (
-- your defaults record
select
default1 as col1,
default2 as col2,
...) as d
left join actual as a
on ((1 = 1) /* or any actual table "where" conditions */)
The query need to return the same number of fields, so you shouldn't do a SELECT * FROM but a SELECT value FROM if you want to return a default value.
With that in mind
SELECT value FROM MyTable WHERE Id = 2
UNION
SELECT CASE (SELECT count(*) FROM MyTable WHERE Id = 2)
WHEN 0 THEN 'defaultvalue'
END