single query to print all the rows whose count is greater than 10 - mysql

I have a table named Table1 whose definition is as below.
Id int False
Source nvarchar(MAX) True
Dest nvarchar(MAX) True
Port nvarchar(MAX) True
DgmLen nvarchar(MAX) True
Flags nvarchar(MAX) True
Payload nvarchar(MAX) True
Now I want to print all the rows of this table whose "source" count is greater than 10.
Firstly I have used this query to fetch the count of sources in the table:
Select Source,count(*) t_count from Table1 group by Source
and it has has fetched the following data:
Source t_count
2-170.125.32.3 1
2-172.125.32.10 1
2-190.125.32.10 11
2-190.125.32.3 1
2-192.125.32.10 1
2-192.125.32.3 6
Now I want to print all the rows having "Source = 2-190.125.32.10" as its t_count is greater than 10.
How can write this in a single query.

If I got you correctly, then :-
select * from Table1 where Source in
(
Select Source from Table1 group by Source having count(*) > 10
)
This return all those rows from Table1 who have the Source column value appearing more than 10 times.
EDIT :-
select * from Table1 t1 join
(Select Source, Dest from Table1 group by Source, Dest having count(*) > 10) t2
on t1.Source = t2.Source and t1.Dest = t2.Dest
Here, the table t2 returns combination of Source, Dest appearing more than 10 times and joins it with the base table Table1.

having "Source = 2-190.125.32.10"
that's the Keyword: having:
Select Source,count(*) t_count from Table1 group by Source HAVING t_count > 10
and btw: if you are grouping by Soruce - there will be ALWAYS exactly one Result Row, that matches a certain source - that's the point of grouping.

Select
s.Source,
s.Dest,
s.Port,
s.DgmLen,
s.Flags,
s.Payload
from Table1 s
join
(
select
source,
count(*) as tot
from Table1
group by source
having tot > 10
)s1
on s1.source = s.source

Your single query should be like this
Select Source,count(*) t_count from Table1 group by Source HAVING t_count > 10
Similar EXAMPLE made

Related

mysql update one table with select sum() from another

I have the following query, which works:
select filename, hour, sum(joe) as joe_total, sum(bob) as bob_total
from t1
group by filename, hour
This gives thousands of rows of data under the following columns:
filename, hour, joe_total, bob_total
Each filename contains 24 hours, so the first row of results would be
filename1, 1, [joe_total_value_hour1], [bob_total_value_hour1]
... and the second row would be
filename1, 2, [joe_total_value_hour2], [bob_total_value_hour2]
... etc.
I have another table called t2 with the following fields:
filename, hour, joe_total, bob_total, mary_total, gertrude_total
The table t2 also has thousands of rows (more than the result of the select above), but currently the columns joe_total and bob_total contain only zeros and need to be updated.
So I want to update t2 so that
t2.joe_total = [resuls from the select].joe_total
and similarly for t2.bob_total for each filename/hour.
Any ideas how I could accomplish this?
Okay, so here's the query that worked:
update t2 t2u
inner join
(SELECT filename, HOUR , SUM( joe) ) AS joe_total, SUM( bob ) AS bob_total FROM t1 GROUP BY filename, HOUR) t
on (t2u.filename =t.filename and t2u.hour = t.hour)
SET t2u.joe_total = t.joe_total,
t2u.bob_total = t.bob_total,
...
Many thanks to Jon C for helping to break my mental icejam.
You can try something like this:
UPDATE t2 SET
t2.joe_total = t.joe_total,
t2.bob_total = t.bob_total,
...
FROM
(
select filename, hour, sum(joe) as joe_total, sum(bob) as bob_total
from t1
group by filename, hour
) t
WHERE t2.filename = t.filename
AND t2.hour = t.hour

repeat result multiple times in mysql

I have a table having id and no field, what I really want is the result raw will be repeated no filed times, if the no field is 2 then that raw must be repeated twice in result.
this is my sample table structure:
id no
1 3
2 2
3 1
now I need to get a result like:
1 3
1 3
1 3
2 2
2 2
3 1
I tried to write mysql query to get the result like above, but failed.
You need a table of numbers to accomplish this. For just three values, this is easy:
select t.id, t.no
from t join
(select 1 as n union all select 2 union all select 3
) n
on t.no <= n.no;
This query must do what you want to achieve:
select t.id, t.no from test t cross join test y where t.id>=y.id
not completely solve your problem, but this one can help
set #i=0;
select
test_table.*
from
test_table
join
(select
#i:=#i+1 as i
from
any_table_with_number_of_rows_greater_than_max_no_of_test_table
where
#i < (select max(no) from test_table)) tmp on no >= i
order by
id desc
EDIT :
This is on SQL Server. I checked online and see that CTEs work on MySQL too. Just couldn't get them to work on SQLFiddle
Try this, remove unwanted columns
create table #temp (id int, no int)
insert into #temp values (1, 2),(2, 3),(3, 5)
select * from #temp
;with cte as
(
select id, no, no-1 nom from #temp
union all
select c.id, c.no, c.nom-1 from cte c inner join #temp t on t.id = c.id and c.nom < t.no and c.nom > 0
)
select * from cte order by 1
drop table #temp

update row if count(*) > n

my DB has this structure:
ID | text | time | valid
This is my current code. I'm trying to find a way to do this as one query.
rows = select * from table where ID=x order by time desc;
n=0;
foreach rows{
if(n > 3){
update table set valid = -1 where rows[n];
}
n++
}
I'm checking how many rows exist for a given ID. Then I need to set valid=-1 for all rows where n >3;
Is there a way to do this with one query?
You can use a subquery in the WHERE clause, like this:
UPDATE table
SET valid=-1
WHERE (
SELECT COUNT(*)
FROM table tt
WHERE tt.time > table.time
AND tt.ID = table.ID
) > 3
The subquery counts the rows with the same ID and a later time. This count will be three or less for the three latest rows; the remaining ones would have a greater count, so their valid field would be updated.
Assuming that (id,time) has a UNIQUE constraint, i.e. no two rows have the same id and same time:
UPDATE
tableX AS tu
JOIN
( SELECT time
FROM tableX
WHERE id = #X -- the given ID
ORDER BY time DESC
LIMIT 1 OFFSET 2
) AS t3
ON tu.id = #X -- given ID again
AND tu.time < t3.time
SET
tu.valid = -1 ;
update table
set valid = -1
where id in (select id
from table
where id = GIVEN_ID
group by id
having count(1) >3)
Update: I really like dasblinkenlight's solution because is very neat, but I wanted to try also to do it in my way, a quite verbose one:
update Table1
set valid = -1
where (id, time) in (select id,
time
from (select id,time
from table1
where id in (select id
from table1
group by id
having count(1) >3)
-- and id = GIVEN_ID
order by time
limit 3, 10000000)
t);
Also in SQLFiddle
to do it for all ids, or only for one if you set a where in the a subquery
UPDATE TABLE
LEFT JOIN (
SELECT *
FROM (
SELECT #rn:=if(#prv=id, #rn+1, 1) AS rId,
#prv:=id AS id,
TABLE.*
FROM TABLE
JOIN ( SELECT #prv:=0, #rn:=0 ) tmp
ORDER BY id, TIMESTAMP
) a
WHERE rid > 3
) ordered ON ordered.id = TABLE.id
AND ordered.TIMESTAMP = TABLE.TIMESTAMP
AND ordered.text = TIMESTAMP.text
SET VALID = -1
WHERE rid IS NOT NULL

Select a row with least value of a column using where and group by

Sample table:
id------user_id------grade_id------time_stamp
1---------100----------1001---------2013-08-29 15:07:38
2---------101----------1002---------2013-08-29 16:07:38
3---------100----------1001---------2013-08-29 17:07:38
4---------102----------1003---------2013-08-29 18:07:38
5---------103----------1004---------2013-08-29 19:07:38
6---------105----------1002---------2013-08-29 20:07:38
6---------100----------1002---------2013-08-29 21:07:38
I want to select rows whose user_id = 100 group by grade_id only if its time_stamp is least for that particular grade_id.
so, from the above table, it should be:
row 1 because its time_stamp is least for that value of grade_id(1001)
but not row 2 because I only want 1 row for a particular grade_id
also not row 6 because that particular grade_id has least value for user_id 105.
I tried few things, which are too basic and obviously not worth posting.
Thank You
You could try nested queries:
SELECT grade_id, COUNT(grade_id) FROM SAMPLE_TABLE ST WHERE time_stamp = (SELECT MIN(time_stamp) FROM SAMPLE_TABLE STT WHERE STT.grade_id = ST.grade_id) AND user_id = 100 GROUP BY grade_id;
In this case, the nested query will give you the minimun timestamp for each specific 'grade_id' and you can use it in your WHERE filter.
SELECT t.*
FROM tableX AS t
JOIN
( SELECT grade_id, MIN(time_stamp) AS time_stamp
FROM tableX
GROUP BY grade_id
) AS g
ON g.grade_id = t.grade_id
AND g.time_stamp = t.time_stamp
WHERE t.user_id = 100 ;

Don't return any result if the precedent query has at least 1 result?

Basically I have this query:
( SELECT * FROM tbl WHERE type = 'word1' )
UNION
( SELECT * FROM tbl WHERE type = 'word2' ) // Run this query if there are no results with type = 1
Basically I would like to run the second query only if the first hasn't any results. is it possible?
The FIRST "PreCheck" query does a count of how many records ARE of type = 1. After that, if the count is greater than 1, then return 1, otherwise return 2.
Now, THAT answer can be used in the join (which is always a single row via COUNT(*)) which will either have a 1 or 2 value. THAT value will be the second value is the EQUALITY conditon. So, if there IS an entry of 1, the result will be as if
WHERE t1.Type = 1
Thus never allowing any 2 in the test. HOWEVER, if NO entries are found, it will have a value of 2 and thus create a WHERE clause of
WHERE t1.type = 2
select t1.*
from
( select if( count(*) > 0, 1, 2 ) IncludeType
from tbl t2
where t2.type = 1 ) preCheck,
tbl t1
where
t1.type = preCheck.IncludeType
If there is an index on the "type" column, the first query should be almost instantaneous.
You could write
select * from tbl
where type = 1
union
select * from tbl
where type = 2
and not exists( select * from tble where type = 1 )
but this probably won't perform as well as just doing it in your program
It does the trick:
SELECT tbl.* FROM tbl JOIN (SELECT min(type) min_type FROM tbl WHERE type between 1 and 2 ) on min_type = type
First, it selects the lesser of these two types, if any exists, and then oins this one number table to your table. It is actually a simple filter. You can use WHERE instead of JOIN, if you want.
SELECT tbl.* FROM tbl WHERE (SELECT min(type) FROM tbl WHERE type between 1 and 2 ) = type