Count users and groups totals in one query - ms-access

I am super new to access and having difficulty with a query. My table (tblpacks) is the following:
id user_id group_id quota_id
1 1 1 1
2 1 2 1
3 2 1 1
4 3 1 1
Ideally, what I now is to get hte number of unique users and groups for quota_id=1
The result will be:
total_users = 3
total_groups = 2

If you only wanted to count one field, there would by a simple solution, but since you want to count 2 separate fields, you in fact need at least 2 separate queries.
My answer is to use a UNION query as the source for counting. This UNION query returns the distinct user_id values (with Null as group_id) and the distinct group_id values (with Null as user_id). I omitted the DISTINCT keyword, because UNION (without ALL) does a DISTINCT query automatically. As the datatypes where not recognized correctly when using a constant Null field in the first SELECT statement of the UNION query, I added a third SELECT statement as the first one, which selects both fields from the table but returns no records:
SELECT Count(user_id) AS total_users, Count(group_id) AS total_groups
FROM (
SELECT user_id, group_id FROM tblpacks WHERE Yes=No
UNION
SELECT user_id, Null FROM tblpacks WHERE quota_id=1
UNION
SELECT Null, group_id FROM tblpacks WHERE quota_id=1
) AS qsub;

Related

How many rows can the following SQL query return?

sql. There is a table T with an id field (optionally unique) that contains N rows. How many rows can the following SQL query return?
select * from T
inner join (
select count(*) as cnt from T
union all select count(*) as cnt from T
) as TA on TA.cnt = T.id
inner join (
select count(*) as cnt from T
union select count(*) as cnt from T
) as TB on TB.cnt = T.id;
I have some options:
only N rows
from 0 to N rows
from 2N to 4N rows
or can you name some other options ?
This query returns either no rows or 2 rows (with all three columns having the same value).
Rationale:
The union all subquery (aliased TA) returns 2 rows, each containing the same value, that is the count of records in T.
The union subquery deduplicates its result and returns a single record, also containing the row count of the table
What happens next depends whether there is a record in the table whose id is equal to that number.
If such record exists, then the query returns 2 rows: one for each row generated by the union all subquery.
If there is no such record, the query return no rows at all.
So assuming this dataset:
id
--
1
2
There are two rows in the table, and id 2 exists, so the query gives you two rows with that id.
If we change this to:
id
--
1
2
3
5
There are four rows but not id 4. The query comes up empty.
0 rows if T.Id does not contain the value 2.
2 rows id T.Id contains the value 2

How can I get all affected row ids in mysql group by sentence?

I am doing a selection using GROUP BY, so I get a lot of different rows. What I need is to UPDATE the status field of each row affected by the SELECT query, but it is grouped... so I don't know all the ids, just the MAX(id).
This is the select query:
SELECT d.*, n.* FROM
(SELECT MAX(id) as id, MAX(datetime) as datetime, COUNT(DISTINCT content) as total FROM user_notifications
WHERE id_user
GROUP BY id_ref, type
ORDER BY datetime DESC) d
JOIN user_notifications n USING (id)
Edit:
Simple example, this is the table
id user content status
1 1 aaa 0
2 1 aaa 0
3 1 bbb 0
4 2 aaa 0
5 3 bbb 0
this is the query
select max(id), user, content from table where user=1 group by content
this is the result
id user content
2 1 aaa
3 1 bbb
in this query in fact sql internally select all user=1 (id= 1, 2, 3) and then the query is grouped, showing just two rows.
So, I want to update all ids involved in the query (id= 1 , 2 and 3)
Based on your example, you need the result exact to this query:
select id from `table` where user = 1;
But by using the query you provided which groups record by content
select max(id), user, content from `table` where user = 1 group by content
So, in such case you can join same table with derived table:
select id from `table` as t
join (select max(id), user, content from `table` where user = 1 group by content) as dt
on dt.content = t.content and dt.user = t.user;
This query is now equivalent to first straight forward query.

Find duplicates where entries within id are duplicate

id class count day
1 2 5 5
2 2 4 5
3 2 4 5
3 2 4 5
4 2 5 3
4 1 5 3
4 2 5 3
So I have a query for finding all duplicates based on multiple columns, however, this also returns id's where not all entries are duplicate.
In above example, the query should only show/count id 3, as all the entries with id 3 are duplicate. Even though id 4 also has a duplicate, it should not show as it has another entry that is unique.
Any idea how to do this?
If you need rows with id where there is no row with the same id and unique row values then use NOT IN and HAVING
select *
from your_table t1
where t1.id not in(
select id
from your_table
group by id, class, count, day
having count(*) = 1
)
You can use this query : http://sqlfiddle.com/#!9/1a2536/8
select id
from test
group by id
having count(distinct id,class,count,day) = 1 and count(*)>1
you group each rows by id and count how many different row the group has, if the distinct total is 1 and the total row is > 1 , there is only duplicate rows for this id.
It's quite easy, a quick note it's a very bad idea to name a column count :
SELECT id, class, `count`,day, COUNT(*)
FROM myTable
GROUP BY id, class, `count`,day
HAVING COUNT(*) > 1
edit : I misread the question so here is my solution :
SELECT test.id, test.class, test.count, test.day , count(*), t.countID
FROM (SELECT id, Count(id) AS countID FROM test GROUP BY id ) t
INNER JOIN test on t.id = test.id
GROUP BY test.id, test.class, test.count, test.day
HAVING Count(*) > 1 AND t.countID = count(*)
I came up with this :
SELECT *
FROM (SELECT id,
Count(id) AS matched
FROM test
GROUP BY id,
class,
count,
day) t
GROUP BY id , matched
HAVING Count(id) = 1
AND matched >= 2
There is maybe a more efficient way to do it but it is easier to understand this way, first we group by every column to find duplicate data. Then the first part of the having eliminates the entries that actually have different variants by id and then we keep only the lines that actually only have duplicates.
Edit : compatible with "only_full_group_by" mode

Insert empty row after group

I have a table that contains transaction data. The rows with the same 'group_id' are a part of the same transaction. I am running the following SQL query to show all the transactions:
SELECT * FROM transactions
When I run this query I get as expected a list of all the transactions. But this large list makes it difficult to seperate the data with a different group_id from the other data.
For that reason I want to add an empty row at the end of the group_id, so I get:
1
1
(empty row)
2
2
2
instead of:
1
1
2
2
2
Can someone help me with this?
Here is my database:
http://sqlfiddle.com/#!9/b9bf79/1
I do not suggest you do this at all but if you just want to separate two groups you could do this:
SELECT * FROM transactions WHERE group_id = 1
UNION ALL
(SELECT '','','','','','')
UNION ALL
SELECT * FROM transactions WHERE group_id = 2
Obviously this can added to if there are more group ids in the future but it is not a general purpose solution you are really better off dealing with appearance issues like this in application code.
you can use (abuse) rollup.
SELECT *
FROM transactions
group by group_id, id
with rollup
having group_id is not null
this will insert a row with id set to null after each group_id.
mysql will also sort by group_id because of the group by.
The group by id` makes sure that all rows are shown (your schema does not show it, but I assume id is unique? Otherwise you need to add other fields)
However only id will be null in the extra rows. The other columns repeat the value above.
You can filter them like this:
SELECT
id,
case id is not null when true then date else null end as date,
case id is not null when true then group_id else null end as group_id
-- ....
FROM transactions
group by group_id, id
with rollup
having group_id is not null
Alternatively:
select * from
(SELECT *
FROM transactions
union all
select distinct null, null, group_id, null, null,null from transactions
) as t
order by 3,1
but null values are sorted first, so the "gap" is in front of each section

MySql Select query

I have a table like this
id status
1 Pass
2 Fail
3 Pass
How can I count total rows and rows where status is "Fail" with their id(s) by group_concat in one select query. I am trying to get output like this
total group_concat(id)
3 1,2,3
1 2
Any advice?
you'll need to union two separate queries:
select status,
count(*) as num,
group_concat(id) as ids
from tests as status_stats
union all
select null as status,
count(*) as num,
group_concat(id) as ids
from tests as total_stats