I have a search function set up, where I run multiple queries simultaneously. The top 1000 results of each query are written to a table. (These run async--I am just leaving out the code that I am using to do that)
Insert into Results
Select Top 1000 Text from A where Contains(Text,'"searchString"')
Insert into Results
Select Top 1000 Text from B where Contains(Text,'"searchString"')
Insert into Results
Select Top 1000 Text from C where Contains(Text,'"searchString"')
Then, I select the top 1000 results from that table.
Select Top 1000 * from Results
Would there be a good way to efficiently check, at any point earlier in the process, if there are already 1000 results, and, if there are, cancelling the other queries and selecting the 1000 results ASAP.
The following will likely give you a plan that achieves your desired result of not processing any rows after the 1,000th one has been found.
WITH CTE
AS (SELECT Text
FROM A
WHERE CONTAINS(Text, '"searchString"')
UNION ALL
SELECT Text
FROM B
WHERE CONTAINS(Text, '"searchString"')
UNION ALL
SELECT Text
FROM C
WHERE CONTAINS(Text, '"searchString"'))
INSERT INTO Results
SELECT TOP 1000 Text
FROM CTE
If you setup your result table with an identity column you can achieve your goal using this query (let 'counter' be that column. don't forget to put an index on it)
declare #remaining int
select #remaining = 1000 - (max(counter) - min(counter) + 1) from result
if #result>0
insert into Result (Text) select top (#remaining) Text from MyTable
Also, if you have a list of table names, you can use a while loop and exit if #result is 0.
The following SQL limits the number of rows to 4 from any subsequent query
SET ROWCOUNT 4
SET #Rows = ##ROWCOUNT
Get the number of rows form the preceeding select
so something like
SELECT TOP etc...
SET #Rows = ##ROWCOUNT
SET ROWCOUNT 1000 - #Rows
Will probably error if #row goes below zero
but you an trap this with IF and goto PROC_LABLE
insert into #tt2
SELECT TOP 1000 [sID]
FROM [docSVsys]
where (select count(*) from #tt2) < 1000
But I would still use .NET and TPL.
This will still process all tables but it should process 0 rows once it gets to 1000
Related
I need to begin my selection starting with the second row of data. This query works fine
SELECT Sum(ttimediff) as 'TOTAL IDLE TIME (sec)' FROM temp where ttimediff>#3;
I just need it start with the second row, and read all rows after that.
I have tried FROM temp ORDER BY asc LIMIT 2 where ttimediff>#3; but I believe the limit statement is stopping the selection at 2. I get a syntax error
You can do this with Limit but you need to have 2 Arguments like this :
SELECT * FROM table_name LIMIT 1, 5000
This will skip 1 element and check until 5000
i'm preparing a presentation about one of our apps and was asking myself the following question: "based on the data stored in our database, how much growth have happend over the last couple of years?"
so i'd like to basically show in one output/graph, how much data we're storing since beginning of the project.
my current query looks like this:
SELECT DATE_FORMAT(created,'%y-%m') AS label, COUNT(id) FROM table GROUP BY label ORDER BY label;
the example output would be:
11-03: 5
11-04: 200
11-05: 300
unfortunately, this query is missing the accumulation. i would like to receive the following result:
11-03: 5
11-04: 205 (200 + 5)
11-05: 505 (200 + 5 + 300)
is there any way to solve this problem in mysql without the need of having to call the query in a php-loop?
Yes, there's a way to do that. One approach uses MySQL user-defined variables (and behavior that is not guaranteed)
SELECT s.label
, s.cnt
, #tot := #tot + s.cnt AS running_subtotal
FROM ( SELECT DATE_FORMAT(t.created,'%y-%m') AS `label`
, COUNT(t.id) AS cnt
FROM articles t
GROUP BY `label`
ORDER BY `label`
) s
CROSS
JOIN ( SELECT #tot := 0 ) i
Let's unpack that a bit.
The inline view aliased as s returns the same resultset as your original query.
The inline view aliased as i returns a single row. We don't really care what it returns (except that we need it to return exactly one row because of the JOIN operation); what we care about is the side effect, a value of zero gets assigned to the #tot user variable.
Since MySQL materializes the inline view as a derived table, before the outer query runs, that variable gets initialized before the outer query runs.
For each row processed by the outer query, the value of cnt is added to #tot.
The return of s.cnt in the SELECT list is entirely optional, it's just there as a demonstration.
N.B. The MySQL reference manual specifically states that this behavior of user-defined variables is not guaranteed.
Basically I store data in MySql 5.5. I use qt to connect to mysql. I want to compare two columns, if col1 is greater than col2, the count continues, but when col1 is less than col2, count finishes and exits. So this is to count how many rows under some condition at the beginning of column. Is it possible in mysql?
An example:
Col1 Col2
2 1
2 3
2 1
The count I need should return 1, because the first row meets the condition of Col1 > Col2, but the second row doesn't. Whenever the condition is not meet, counting exits no matter if following rows meet the condition or not.
SELECT COUNT(*)
FROM table
WHERE col1 > col2
It's a little difficult to understand what you're after, but COUNT(*) will return the number of rows matched by your condition, if that's your desire. If it's not, can you maybe be more specific or show example(s) of what you're going for? I will do my best to correct my answer depending on additional details.
You should not be using SQL for this; any answer you get will be chock full of comprimise and if (for example) the result set from your intial query comes back in a different order (due to an index being created or changed), then they will fail.
SQL is designed for "set based" logic - and you really are after procedural logic. If you have to do this, then
1) Use a cursor
2) Use an order by statement
3) Cross fingers
This is a bit ugly, but will do the job. It'll need adjusting depending on any ORDER etc you would like to apply to someTable but the principle is sound.
SELECT COUNT(*)
FROM (
SELECT
#multiplier:=#multiplier*IF(t.`col1`<t.`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) scanQuery
The #multiplier variable will keep multiplying itself by 1. When it encounters a row where col1 < col2 it multiplies by 0. It will then continue multiplying 0 x 1. The outer query then just sums them up.
It's not ideal, but would suffice. This could be expanded to allow you to get those rows before the break by doing the following
SELECT
`someTable`.*
FROM `someTable`
INNER JOIN (
SELECT
`someTable`.`PrimaryKeyField`
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) t
ON scanQuery.`PrimaryKeyField` = `someTable`.`PrimaryKeyField`
Or possibly simply
SELECT
`someTable`.*
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
I encountered sql queries like 'SELECT 1 FROM TABLE_NAME' or 'SELECT 2 FROM TABLE_NAME' while debugging a program. I am curious as to what the numbers in the queries do and what result set does it return.
Thanks
It will return a single column with the number as value, with n rows, n being the number of rows returned from the select.
This is usefull in cases such as
SELECT *
FROM YourTable yt
WHERE EXISTS(
SELECT 1
FROM SomeOtherTable sot
WHERE yt.ID = sot.ID
)
Also, good article at SELECT 1 vs SELECT * – An Interesting Observation
Select 1 from your_table --> On execution , you get the value 1 for every row in your_table.
'Select *' and 'Select 1 or 2' have the same performance when executing without an EXIST condition. My personal choice is using 'Select 1 or 2' when there are conditions to check for existing rows as it is slightly faster, for eg. when querying with VIEWS or temp tables having millions of rows and lot many columns.
I have a stored procedure which returns multiple result sets similiar to the following:
ALTER PROCEDURE sp_XXXX
(
XXXXXX
)
AS
SET NOCOUNT ON
SELECT XXXXXXX
IF ##ROWCOUNT = 0
SELECT XXXXXXX
RETURN
I want my report to use the first result set if it has data or use the second one in case the first one is empty. Any help?
In the sproc "union all" your two result sets. If you need to tell them apart add a derived column indicating the original result set.
select 'ds1' as dataset, *
from table1
union all
select 'ds2' as dataset, *
from table2
Another try
Dump result set 1 into a temp table and only execute the second query if it's empty.
pseudo code:
select * into #tempResult
from table 1
if table1 is empty
select * from table2