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
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 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
I've written a query which should take all the rows from one table and do a subquery to a second table pulling only one value from the most recent record. In SQL Server the query takes about 15 seconds to execute and the LINQ query takes close to 2 minutes. Can someone help me with translating the SQL to LINQ, I must have done something wrong along the way.
The SQL:
SELECT a.isrunning,
worktype = (
SELECT TOP 1
w.worktype
FROM dbo.workorder w WITH (NOLOCK)
WHERE w.assetnum = a.assetnum
ORDER BY w.statusdate DESC
),
a.status,
*
FROM dbo.asset a WITH (NOLOCK)
WHERE a.assetnum IN ('list', 'of', 'asset', 'numbers')
The LINQ Query:
(
from a in db.assets
let wo = (
from w in db.workorders
where w.assetnum == a.assetnum
orderby w.statusdate descending
select w).FirstOrDefault()
where aliasStrings.Contains(a.assetnum)
select new AssetWithWorkType {
...
}
);
It is recommended to have indexes on foreign keys. Also indexes that covers filtering and ordering clauses. So I suggest you to create the following 3 indexes:
CREATE NONCLUSTERED INDEX [IDX_workorder_statusdate] ON dbo.workorder(statusdate)
CREATE NONCLUSTERED INDEX [IDX_workorder_assetnum] ON dbo.workorder(assetnum)
If assetnum column in asset table is not the primary key then additionally:
CREATE NONCLUSTERED INDEX [IDX_asset_assetnum] ON dbo.asset(assetnum)
You can create a temp table for the correlated subquery results, and then join it later. Syntax is not correct, as I dont have your table schemas or data, but the idea is the same.
CREATE TABLE #workTypes (worktype VARCHAR(X), assetnum VARCHAR(x))
INSERT INTO #workTypes
SELECT TOP 1 worktype, assetnum FROM dbo.workorder ORDER BY statusdate DESC
SELECT a.isrunning,
b.worktype,
a.status,
*
FROM dbo.asset a WITH (NOLOCK)
INNER JOIN #worktypes b
ON a.assetnum = b.assetnum
WHERE a.assetnum IN ('list', 'of', 'asset', 'numbers')
How about:
SELECT a.isrunning,
w.worktype,
cnt = count(*)
FROM dbo.asset a WITH (NOLOCK)
INNER JOIN dbo workorder w WITH (NOLOCK) on w.assetnum = a.assetnum
WHERE a.assetnum IN ('list', 'of', 'asset', 'numbers')
This would give you a count of worktypes for each asset and might allow the database server to optimize more efficiently. Also consider adding indices or using a temp table as other answers have suggested.
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 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'