Having count on result of Group_Concat - c#

I have applied the Group_Concat on my query and the results are displayed just fine. Below is my query,
SELECT tblUserGroup.GroupID, GROUP_CONCAT(tblUserGroup.UserId) AS UserIds FROM
tblGroup
INNER JOIN tblUserGroup ON tblGroup.GroupID = tblUserGroup.GroupID
GROUP BY tblUserGroup.GroupID
ORDER BY (UserIds)
NOW the ouput is something like this.
GroupID UserIds
1 1,2
2 1,4
3 1,2,3
4 1,2
5 1,2
6 1,2,3
I have read different questions on GROUP_CONCAT and COUNT but I want to apply count not on UserId rather I want to apply count on theGROUP_CONCAT such as "1,2".
What I want is to modify this query such that it only display those records which occurs more then one time. For example just 1,2 and 1,2,3

Have you tried to use subquery? It would be something like:
SELECT Sub.UserIds, COUNT(*) as Qt
FROM (
SELECT tblUserGroup.GroupID, GROUP_CONCAT(CONVERT(tblUserGroup.UserId, CHAR(20)) SEPARATOR ',') AS UserIds, count(*) FROM
tblGroup
INNER JOIN tblUserGroup ON tblGroup.GroupID = tblUserGroup.GroupID
GROUP BY tblUserGroup.GroupID HAVING COUNT(*) > 0
) AS Sub
GROUP BY Sub.UserIds

Maybe you can use count and use below query (I could not test it):
SELECT tblUserGroup.GroupID, GROUP_CONCAT(tblUserGroup.UserId) AS UserIds, count(*) FROM
tblGroup
INNER JOIN tblUserGroup ON tblGroup.GroupID = tblUserGroup.GroupID
GROUP BY tblUserGroup.GroupID HAVING COUNT(*) > 0
ORDER BY (UserIds)

Related

SQL query for paging received records

I want to write a query that receives informations about customers and their orders from another table and show them in this way:
Customer 1
Customer 1 Order 1
Customer 1 Order 2
Customer 2
Order 1 Customer 2
Customer 3
Order 1 Customer 3
....
And I want to do paging by Customers. For example - if I define items per page = 10, I want to show 10 customers, no matter how many orders they had.
I prepared this query but I think it's not gonna work properly and I don't know how to solve this..
var result = db.Page<Customer>(pageNumber, 10, "SELECT c.*, o.* FROM Customers c JOIN Orders o
ON o.Id = c.Id");
You can use dense_rank() and filter on that:
SELECT c.*, o.*, DENSE_RANK() OVER (ORDER BY c.id) as seqnum
FROM Customers c JOIN
Orders o
ON o.Customer_Id = c.Id;
You need to use WHERE for filtering, rather than LIMIT or FETCH or whatever.

MySql Split Query Group Percentage

I am trying to do the following but I cannot manage to get it right yet :(.
I have these tables:
table1 -> tb1_id, tb1_name
Sample Data:
--------------
1 group1
2 group2
3 group3
4 group4
5 group5
table2 -> tb2_id, tb2_sector, tb2_tb3_id
Sample Data:
--------------
1 alpha 1
2 beta 2
3 gamma 2
4 delta 2
5 epsilon 4
table3 -> tb3_id, tb3_mid, tb3_section
Sample Data:
--------------
1 234 alpha,beta,gama,delta
This is the output that I am looking for:
Name Count %
------ ----- -----
group1 1 25%
group2 3 75%
group3 0 0%
group4 0 0%
group5 0 0%
Basically I need a split a column value delimited by a comma (tb3_section in table3) and then find the right group for each value (table2 gives me the group id to link with table1) and then do a total count by group and get the percentage (assuming total is 100%).
This is the query I tried so far:
I searched for split value samples and found one that does the split by creating a numbers table first:
create table numbers (
`n` INT(11) SIGNED
, PRIMARY KEY(`n`)
)
INSERT INTO numbers(n) SELECT #row := #row + 1 FROM
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t,
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
(SELECT 0 UNION ALL SELECT 1) t8,
(SELECT #row:=0) ti;
Afterwards, I did this:
select tb3_section, count(1) from (
select
tb3_mid,
substring_index(
substring_index(tb3_section, ',', n),
',',
-1
) as tb3_section from table3
join numbers
on char_length(tb3_section)
- char_length(replace(tb3_section, ',', ''))
>= n - 1
) tb3_section_dashboard
group by 1
This doesn't give me the group count. Just does the split of tb3_section but doesn't give me the correct count and equivalent percentage. Any ideas will be much appreciate it thanks a lot.
LATEST UPDATE
First of all, I would like to thanks #eggyal for pointing me to the right direction and #Shadow for despise knowing that I was not taking the best approach, he came up with a quick fix to my problem. I managed to change the approach and removed the comma delimited values from table3. Instead now I add multiple rows for each new value (and added a constraint to avoid duplicates).
Now table3 looks like:
Sample Data:
--------------
1 234 alpha
2 234 beta
3 234 gama
4 234 delta
5 235 alpha
Here is the query I have taken from #shadow sample:
SELECT t1.tb1_name, COUNT(t3.tb3_section) AS no_per_group,
COUNT(t3.tb3_section) / t4.no_of_groups AS percentage
FROM t1 left
JOIN t2 ON t1.tb1_id=t2.tb2_tb3_id
INNER JOIN t3 ON t2.tb2_sector=t3.tb3_section>0
JOIN (SELECT COUNT(*) AS no_of_groups
FROM t3 INNER JOIN t2 ON t2.tb2_sector=t3.tb3_section>0) t4
GROUP BY t1.tb1_name
Instead of using find_in_set now I use = to match the exact value.
Now I get something like the following but the percentage looks odd and I miss a group that doesn't have a match:
Name no_per_group percentage
----- ------------- ----------
group1 2 0.1053
group3 3 0.1579
group4 3 0.1579
group5 3 0.1579
Although still I need something like:
Name Count %
------ ----- -----
group1 1 25%
group2 3 75%
group3 0 0%
group4 0 0%
group5 0 0%
Notice that if there is no match in a group, I still need to show that group.
Because I have thousands of records which are different from each other, I need to add another condition: where tb3_mid=234 . Likes this, the results are using to tb3_mid.
The best solution would be to redesign your table structure and move the data in the delimited values list to a separate table.
The quick solution is to utilise MySQL's find_in_set() function.
To get the total count of entries in the messages table (table3):
select count(*) as no_of_groups
from t3 inner join t2 on find_in_set(t2.tb2_sector,t3.tb3_section)>0
To get the counts per group, add a join to table1 and group by group name. To calculate the percentage, add the above query as a subquery:
select t1.tb1_name, count(t3.tb3_section) as no_per_group, count(t3.tb3_section) / t4.no_of_groups as percentage
from t1 left join t2 on t1.tb1_id=t2.tb2_tb3_id
inner join t3 on find_in_set(t2.tb2_sector,t3.tb3_section)>0
join (select count(*) as no_of_groups
from t3 inner join t2 on find_in_set(t2.tb2_sector,t3.tb3_section)>0) t4 --no join condition makes a Cartesian join
group by t1.tb1_name

get same result from c# linq as SQL statement

I am trying to figure out how to get all the notifications from relations that get multiple notifications, because i want to combine these notifications to 1 notification so the relation wil only get 1 e-mail instead of multiple.
I created the following SQL statement, which for as far as i can tell does what i want:
select distinct r.Notificatie
, r.RelatieNr
FROM [configuratie].[dbo].[NotificatieRecID] r
join [configuratie].[dbo].[Notificatie] n on r.Notificatie = n.ID
where n.Verzonden = 0
and r.RelatieNr in(select RelatieNr from [configuratie].[dbo].[NotificatieRecID]
group by RelatieNr having count(*) > 1)
order by r.RelatieNr
It returns the following
Notification Relation
3A2A53B9-D92A-4504-874D-5A901AD01041 114147
4C499F6C-53C8-49E0-B529-8B045819BE10 114147
AF4ED8CB-D033-47A4-96AE-F379BB484532 114147
977885C5-4C12-431B-AB72-59383B1824C6 303327
3A2A53B9-D92A-4504-874D-5A901AD01041 303327
4C499F6C-53C8-49E0-B529-8B045819BE10 303327
AF4ED8CB-D033-47A4-96AE-F379BB484532 303327
Later in my c# code i will get all the values from the different notifications and simply combine them but first i need to write this SQL statement in a way i can use it with linq in c#.
I have no idea how to do SELECT DISTINCT, and r.RelatieNr in and group by RelatieNr having count(*) > 1
Could someone provide me with an example? (it does not have to be 1 linq statement, i've kind of figured that's impossible, though i would like as little temporary Lists/Iqueriables since the tables are huge)
You can use the following
var details= (from r in NotificatieRecID
join n in Notificatie on r.Notificatie=n.ID
where n.Verzonden=0 &&
(from t in NotificatieRecID
group t by t.RelatieNr into grp
where grp.Count()>1
select grp.Key).Contains(r.relatieNr)
select new {
Notificate=r.Notificatie,
RelatieNr=r.RelatieNr
}).Distinct();

Get top five most repeating records in Entity Framework

I want to get top five most repeating records from a table in link to Entity Framework 4.0. How it can be possible in a single query which returns a list of collection of five records?
You simply group by count, order descending by count and then Take(5). Grouping examples, amongst others, can be found at 101 LINQ Samples.
Actually you should group by fields which define whether record is repeating or not. E.g. in your case it should be something like member id. Then you can introduce new range variable which will keep number of records in each group. Use that variable for ordering results:
var query = from s in db.Statistics
group s by s.MemberId into g // group by member Id
let loginsCount = g.Count() // get count of entries for each member
orderby loginsCount descending // order by entries count
select new { // create new anonymous object with all data you need
MemberId = g.Key,
LoginsCount = loginsCount
};
Then take first 5:
var top5 = query.Take(5);
That will generate query like
SELECT TOP (5) // Take(5)
[GroupBy1].[K1] AS [MemberId], // new { MemberId, LoginsCount }
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
[Extent1].[MemberId] AS [K1],
COUNT(1) AS [A1] // let loginsCount = g.Count()
FROM [dbo].[Statistics] AS [Extent1]
GROUP BY [Extent1].[MemberId] // group s by s.MemberId
) AS [GroupBy1]
ORDER BY [GroupBy1].[A1] DESC // orderby loginsCount descending

Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

This may be a very silly mistake but I just can't fix it. I have 2 tables, Questions and Questions_Rating.
Questions:
question_id question user_id
------------------------------------------
1 'How to blablabla' 1
2 'bla bla bla' 1
Questions_Rating
In this table, users will rate questions either by +1 or -1
question_rating_id question_id user_id rate
------------------------------------------------------
1 1 2 (+1)
2 1 3 (+1)
3 1 4 ( 1)
Now I would simply like to fetch the question from the questions table, and the SUM of the rate in the questions_rating table for this question, which has an ID = 1.
String QUERY = "SELECT q.question, SUM(r.rate) FROM questions q, questions_rating r WHERE r.question_id = q.question_id AND q.question_id = 1";
And this is what I'm getting.
Column 'questions.question' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know that the SUM of the rate will return 1 row, and the question is supposedly 1 row, I can't figure out what's wrong with this query.
I am using SQL Server 2008.
You will have to Group the values as per the question so you need a
GROUP BY q.question
at the end of your query
Good Explanation here
You need the group by q.question in your SQL statement.
Your Sum is suppose to return only a single row against the table, since you are selecting a column along with the Sum you need to specify a group on the selected column. In your case it should be q.question, and sum will be applied to each group of questions.
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q,questions_rating r
WHERE r.question_id = q.question_id AND q.question_id=1
GROUP BY q.question
or (using ANSI 92 style joins)
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q INNER JOIN questions_rating r ON r.question_id = q.question_id
WHERE q.question_id=1
GROUP BY q.question
or (using subqueries)
SELECT q.question, (SELECT SUM(r.rate) FROM questions_rating r WHERE r.question_id = q.question_id) AS RateSum
FROM questions q
WHERE q.question_id=1
You are missing group by clause in your select statement.
As you have used sum() function which is an aggregate function
So you need to write group by for all the select columns.
String QUERY = "SELECT
q.question,
SUM(r.rate)
FROM
questions q,
questions_rating r
where
r.question_id = q.question_id AND
q.question_id=1
group by
q.question";

Categories

Resources