I have to query from a table or a view on two condition. I could repeat it with if conditions, but in my scenario it need to be in one query,
Something like a procedure that is receiving a flag #reportType int
SELECT
a, b, c, d, e, f, g, h,... and so many
FROM
CASE
WHEN #reportType = 1
THEN table
ELSE View
END
INNER JOIN
and so on..
I need to write like above but it is throwing an error
Incorrect syntax near the keyword 'CASE'
In your stored procedure, you need to use an if statement instead:
if #reportType=1
SELECT a,b,c FROM myTable
else
SELECT a,b,c FROM myView
Actually this does not look like a good design, but if you have to work with this and wish to avoid copy-past, you may try conditional CTEs with final union or one subquery with union to imitate single source for final query:
;with Source_1 as
(
select ...
from myTable
where #reportType=1
),
Source_2 as
(
select ...
from myView
where #reportType=2
),
FullSource
(
select ...
from Source_1
union all
select ...
from Source_2
)
select ...
from FullSource src
inner join ...
or
select ...
from
(
select ...
from myTable
where #reportType = 1
union all
select ...
from myView
where #reportType = 2
) src
inner join ...
Note, different possible flows confuse query optimizer and this code is not good for performance. For some better execution plan you will probably need to enable recompile option.
You can use dynamic SQL as below:
DECLARE #reportType INT
SET #reportType = 1
DECLARE #q VARCHAR(max)= 'SELECT
a, b, c, d, e, f, g, h,... and so many
FROM '+
CASE
WHEN #reportType = 1
THEN 'table '
ELSE 'View '
END+'
INNER JOIN
and so on..'
EXEC(#q)
You may also want to use sp_executesql in order to make the query parametric and prevent the possible SQL injection.
I think you need a query like this:
;WITH mixedData AS (
SELECT yourFields, 1 As reportType
FROM yourTable
UNION ALL
SELECT yourFields, 2 AS reportType
FROM yourView
)
SELECT *
FROM mixedData
INNER JOIN yourJoinParams
WHERE mixedData.reportType = #reportType;
or
...
WHERE mixedData.reportType =
CASE WHEN #reportType = 1 THEN 1 ELSE 2 END;
Note that yourFields from yourTable and yourView are same.
HTH
Related
In sql I can do this
select 'a' as MyColumn
so, i have a query in linq with entity framework that get some data from the database, but, i need union that query with one row, and in sql I can do this:
select ... from ...
union
select 'a' as MyColumn
How can i generate this query with linq?
I tried to do this:
var query = (from ... select new {..}).Union(new List<...> { new ...() { MyColumn = 'a' } })
But i gess that Entity Framework DON'T know how to translate that in memory list to sql
I need to get an IQueryable result, not a List or other in memory Collection, because i need to join that result to other sql linq querys in the future.
This isn't possible and you shouldn't do it. Both for the same reason: Entity Framework will try to translate the whole LINQ statement into SQL, including the local list (new List<...>).
The reason why it's not possible is that EF has no way to translate C# objects into SQL constructs.
The reason why you shouldn't do it is that it's incredibly wasteful: you build the list in C# code, EF (if it could) translates it into a SQL statement, the database runs the SQL statement and converts it to a result set, EF receives the result set and converts it into the list you originally offered it.
Just to demonstrate it, I'll show what happens if you do this with a list of primitive values which EF does know how to translate into SQL:
var ints = Enumerable.Range(1,5);
var res = Products.Select(c => c.Id).Union(ints).ToList();
This produces the following SQL statement:
SELECT
[Distinct1].[C1] AS [C1]
FROM ( SELECT DISTINCT
[UnionAll5].[ProductId] AS [C1]
FROM (SELECT
[Extent1].[ProductId] AS [ProductId]
FROM [dbo].[Product] AS [Extent1]
UNION ALL
SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]
UNION ALL
SELECT
3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]
UNION ALL
SELECT
4 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]
UNION ALL
SELECT
5 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll5]
) AS [Distinct1]
As you see, for each element in the list EF generated a SingleRowTablex entry to build a "temp table" to UNION with the ids from the actual query.
Conclusion: just query what you need from the database and add to the result afterwards. It's easy enough to do that:
(from ... select new {..})
.AsEnumerable() // continue in memory
.Union(...)
I tried to set a value to variable in sub query but it doesn't work.
Here is my query:
declare #val1 int
declare #val2 int
select #val1 = sum(column1)
,(select #val2 = (select sum(column2) from table2))
,(#val1+#val2)Result
from table 1
What I want to do is setting #val2 for sub query help me please
I meant set in Sub query not separate select statement
Just use 3 separate selects:
select #val1 = sum(column1) from table1
select #val2 = sum(column2) from table2
select (#val1+#val2) as Result
Or you can also write 2 selects:
select #val1 = sum(column1),
#val2 = (select SUM(column2) from table2)
from table1
select (#val1 + #val2) Result
But not just 1 select:
A SELECT statement that assigns a value to a variable must not be
combined with data-retrieval operations
If you need to accomplish all in one select and return a recordset, do not use variables, do it like this:
SELECT sum1 + sum2 FROM (
select sum(column1) as sum1,
(select SUM(column2) from table2) as sum2
from table1
) subquery
I have a question regarding joining tables.
I have eleven tables, one parent with ten child tables. Primary key on all is EventName with the relationship from parent to child being EventName as well. The child tables names are SR1Laptimes, SR2Laptimes etc x 10.
The schema in the child tables are identical. I'm trying to join Events table to SR1Laptimes and then Union all the child table together but can't get it to work.
There is a method behind this madness but would take some time to explain. Here's the code anyway, any feed back would be greatly appreciated. P.S the codes not finished in this copy and paste.
myCommand.CommandText = "SELECT MIN(Q1), MIN(Q2), MIN(Q3), MIN(Q4), MIN(LaptimesMinutes), MIN(LaptimesSeconds) FROM Events LEFT JOIN SR1Laptimes ON Events.EventName = SR1Laptimes.EventName SELECT * FROM SR1Laptimes UNION ALL SELECT * FROM SR2Laptimes UNION ALL SELECT * FROM SR3Laptimes WHERE (Events.Track = #track) AND (Events.Number = #number) AND (Events.Rider = #rider)";
myCommand.Parameters.AddWithValue("#track", analysisTrackComboBox.Text);
myCommand.Parameters.AddWithValue("#number", analysisNumberComboBox.Text);
myCommand.Parameters.AddWithValue("#rider", analysisRiderComboBox.Text);
I think you are missing an UNION ALL clause at:
... ON Events.EventName = SR1Laptimes.EventName *HERE* SELECT * FROM SR1Laptimes ...
Are the tables you try to 'union all' have same columns? That might be the problem.
And 'where' clause at the end is valid only for SR3Laptimes.
This example may help you.
DECLARE #Parent TABLE (id INT,sth NVARCHAR(100))
DECLARE #ChildTest1 TABLE(id INT,parentId INT, sth NVARCHAR(100))
DECLARE #ChildTest2 TABLE(id INT, parentId INT, sth NVARCHAR(100))
INSERT INTO #Parent
SELECT 1,'Ali'
UNION ALL
SELECT 2,'Veli'
UNION ALL
SELECT 3,'Ahmet'
INSERT INTO #ChildTest1
SELECT 1,1,'Parent1_Child1_1strow'
UNION ALL
SELECT 2,1,'Parent1_Child1_2ndrow'
UNION ALL
SELECT 3,2,'Parent2_Child1_1strow'
INSERT INTO #ChildTest2
SELECT 1,1,'Parent1_Child2_1strow'
UNION ALL
SELECT 2,2,'Parent2_Child2_1strow'
UNION ALL
SELECT 3,3,'Parent3_Child2_1strow'
SELECT * FROM #Parent p
LEFT JOIN (
SELECT * FROM #ChildTest1 ct1
UNION ALL
SELECT * FROM #ChildTest2 ct2
) s ON p.id =s.parentId
--WHERE p.id = 3
I am generating a report in php (mysql),
ex:
`select count(id) as tot_user from user_table
select count(id) as tot_cat from cat_table
select count(id) as tot_course from course_table`
Like this I have 12 tables.
Can i make it in single query. If i did? Process gets slow?
SELECT (
SELECT COUNT(*)
FROM user_table
) AS tot_user,
(
SELECT COUNT(*)
FROM cat_table
) AS tot_cat,
(
SELECT COUNT(*)
FROM course_table
) AS tot_course
If you use MyISAM tables, the fastest way is querying directly the stats:
select table_name, table_rows
from information_schema.tables
where
table_schema='databasename' and
table_name in ('user_table','cat_table','course_table')
If you have InnoDB you have to query with count() as the reported value in information_schema.tables is wrong.
You can certainly us the a Select Agregation statement as Postulated by Ben James, However This will result in a view with as many columns as you have tables. An alternate method may be as follows:
SELECT COUNT(user_table.id) AS TableCount,'user_table' AS TableSource FROM user_table
UNION SELECT COUNT(cat_table.id) AS TableCount,'cat_table' AS TableSource FROM cat_table
UNION SELECT COUNT(course_table.id) AS TableCount, 'course_table' AS TableSource From course_table;
The Nice thing about an approch like this is that you can explicitly write the Union statements and generate a view or create a temp table to hold values that are added consecutively from a Proc cals using variables in place of your table names. I tend to go more with the latter, but it really depends on personal preference and application. If you are sure the tables will never change, you want the data in a single row format, and you will not be adding tables. stick with Ben James' solution. Otherwise I'd advise flexibility, you can always hack a cross tab struc.
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('10544175A')
UNION
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('10328189B')
UNION
select RTRIM(A.FIELD) from SCHEMA.TABLE A where RTRIM(A.FIELD) = ('103498732H')
SELECT t1.credit,
t2.debit
FROM (SELECT Sum(c.total_amount) AS credit
FROM credit c
WHERE c.status = "a") AS t1,
(SELECT Sum(d.total_amount) AS debit
FROM debit d
WHERE d.status = "a") AS t2
I know this is an old stack but i will post this Multi-SQL select case
SELECT bp.bizid, bp.usrid, bp.website,
ROUND((SELECT SUM(rating) FROM ratings WHERE bizid=bp.bizid)/(SELECT COUNT(*) FROM ratings WHERE bizid=bp.bizid), 1) AS 'ratings',
(SELECT COUNT(*) FROM bzreviews WHERE bizid=bp.bizid) AS 'ttlreviews',
bp.phoneno, als.bizname,
(SELECT COUNT(*) FROM endorsment WHERE bizid=bp.bizid) AS 'endorses'
, als.imgname, bp.`location`, bp.`ownership`,
(SELECT COUNT(*) FROM follows WHERE bizid=bp.bizid) AS 'followers',
bp.categories, bp.openhours, bp.bizdecri FROM bizprofile AS bp
INNER JOIN alluser AS als ON bp.usrid=als.userid
WHERE als.usertype='Business'
I want to create a statement like the following:
if (select statement1 returns rows){
select statement2
}
else {
select statement3
}
This if statement is part of a bigger query
select from products where p.id in (
if (select statement1 returns rows){
select statement2
}
else {
select statement3
}
Is this possible in SQL Server, or is my thinking incorrect?
You need to use a combination of EXISTS and CASE..END:
select *
from products
where p.id in (
case when (exists ( <statement1> ))
then ( <statement2> )
else ( <statement3> )
end
)
Where <statement1> might be: SELECT * FROM Customer WHERE Id = 123
<statement2> might be: SELECT MIN(field) FROM someTable
<statement3> might be: SELECT 0 as DefaultValue
If you can show some examples of what you want those actual statements to be I can provide a more concrete answer.
Actually SQL is more rigid, due to performance considerations. Your query will look more like this:
select *
from products
where 1 = case when (exists ( <statement1> ))
then case when p.id in ( <statement2> ) then 1 else 0 end
else case when p.id in ( <statement3> ) then 1 else 0 end
end
Since you are checking for the same id existance, I think you could do a UNION here.
select *
from products
where p.id in (select id from table1
union
select id from table2)
I'd recommend using a UNION between your two conditions to help avoid performance problems...and may be easier to read as well.
SELECT FROM products p
WHERE EXISTS (SELECT STATEMENT1)
AND EXISTS (SELECT STATEMENT2 s2 WHERE s2.p_id = p.id)
UNION
SELECT FROM products p
WHERE NOT EXISTS (SELECT STATEMENT1)
AND EXISTS (SELECT STATEMENT3 s3 WHERE s3.p_id = p.id)
Depending on the nature of the statements, you might be able to leave off the Not Exists in the second select.