Count and distinct in mysql (comma separated data in table) - mysql

I am trying to get the details from mysql database.
My table have location field.
Data is like below
Location
India
UK,Finland, India
USA, NZ, AUS, Spain
I am trying to get the count for each location.
select count(distinct location) from posting
This is the query i have written at the moment for testing purpose. It return me count.
I want to get the details like below.
India -2
UK - 1
Finland -1
USA - 1
Something like that.
Note Please ignore dash as this is just to show you what i want.
Please advise me as i am not good in database.

You should not be storing multiple values in a single columns. Delimited strings are not the right way to store values in SQL. The proper way is a junction table.
If I assume that you have a list of locations, then you can do:
select l.location, count(*)
from location l join
posting p
on find_in_set(l.location, p.location) > 0;
If you don't have such a table, I would recommend that you focus on fixing your data structure first, rather than trying to get such a query to work.

SELECT COUNT(location),location FROM posting;
Try this one out. It will give you a similar output.

Related

MYSQL Group By Returning Duplicate Values

I am seeing a weird problem with MYSQL GROUP BY.
I have a query...
SELECT schools.schoolregion,
Count(schools.schoolregion) AS regioncount,
(
SELECT Count(jobs_jobsubject)
FROM 'jobs'
WHERE 'jobs_createdDate' BETWEEN '$startofyear'
AND '$endofyear') AS regionjobstotal
FROM 'jobs'
LEFT JOIN 'schools'
ON 'jobs_schoolID'='SID'
WHERE 'jobs_createdDate' BETWEEN '$startofyear'
AND '$endofyear'
GROUP BY 'schoolRegion'
...in which I am attempting to total the number of job postings listed per region and group by region. I have two tables, one with a list of schools and another with job information that has a column value that joins back to the school. I need the region total, and the overall total of jobs within a time period (hence the sub query).
When I run this query, I get everything that I expect - except that I am getting a duplicate region listing in the returned results of the GROUP BY function.
For example, here is the table that I am getting but not sure why the duplicate for the Middle East.
schoolRegion regioncount regionjobstotal
Africa 1 38
Asia 6 38
Middle East 20 38
Middle East 11 38
I thought maybe there was an extra character or something, but I could not find/see anything different about the values within the tables - which for that column is being stored as type "text". Is there anything I can check for? Is it something to do with the query?
Any help would be fantastic and much appreciated!!
My guess is that the data is not ordered by schoolRegion. I would add an ORDER BY schoolRegion ASC to your query to ensure that they are organized thusly. :)
OMG, do I feel like a noob!!
When I adjusted the query to list the schools, there was only one school that was not included in the GROUP BY. Initially when I looked at this hours ago, inline editing in PHPMYADMIN didn't show that there was a character return AFTER the text - so I wrote off that it was the text of the value being stored. But when I checked the box to edit the row individually and not inline and went to that column value - low and behold - a carriage return!!! Sometimes it's the little things like that which kill and humble me.
First, i do not think you can supply a child select statement as a column in your parent select statement "(SELECT COUNT(jobs_jobSubject)...".
Also since the where clause for your child and parent select are thesame, why not use a single select statement and get the count of both.
SELECT schools.schoolRegion,
COUNT(schools.schoolRegion) AS regioncount,
COUNT(jobs_jobSubject) AS regionjobstotal
FROM 'jobs' jb
INNER JOIN 'schools' sc ON jb.jobs_schoolID=sc.SID
WHERE 'jobs_createdDate'
BETWEEN '$startofyear' AND '$endofyear'
GROUP BY 'schoolRegion'

\n Separated Search in Column

I have a district table, in which we store user’s preferred districts in district table district_id (varchar(250)) field(column). Value stored in this field is like 1 2 5 6 1 by using \n. So please tell me, how can i search in this specific column?
Don't. Your design is absolutely horrible and this is why you are having this issue in the first place.
When you have a N-N relationship (a user can have many preferred districts and each district can be preferred by many users) you need to make a middle table with foreign keys to both tables.
You need:
A table for districts with only information about districts.
A table with users with only information about users.
A table for preferred districts by user with the district number and the user id as columns and foreign key constraints. This will make sure that any user can have an unlimited number of preferred districts with easy querying.
I would not recommend performing searches on data stored that way, but if you are stuck it can be done with regular expressions.
You have to deal with starting and ending matches for a string as well. So a regular LIKE is not going to work.
MySQL Regular Expressions
Give this SQL a try. To search for the number 5
SELECT * FROM `TABLE` WHERE `field` REGEXP '\\n?(5)\\n?';
If you want to match using the LIKE feature. It can be done using multiple rules.
SELECT * FROM `TABLE` WHERE `field` LIKE '%\\n5\\n%' OR LIKE '5\\n%' OR LIKE '%\\n5';
Note that you have to use a double \ to escape for a new line.
Easiest way is to just use a LIKE query, like this:
SELECT * FROM `preferred_districts` WHERE `district_id` LIKE '%6%';
To make sure it's the right one you'll receive (because this will also match id 16, 26, 674 etc.) you'll have to check manually if it's correct. In php (dunno if you use it) you could use the snippet below:
$id_field = '1 2 5 6 17';
$ids = explode("\n", $id_field);
if(in_array(6, $ids)) {
echo 'Yup, found the right one';
}
Important Although the above will work, your database design isn't how it should be. You should create (what is sometimes called) a pivot table between the districts and the users, something like below.
(Table 'users_preferred_districts')
user_id | district_id
--------+------------
2 | 1
2 | 17
9 | 21
Like this it's quite easy to retrieve the records you want...
I have used mysql function FIND_IN_SET() and I got the desired result through this function.
I got help from this tutorial.
http://www.w3resource.com/mysql/string-functions/mysql-find_in_set-function.php

Forming SQL query

In my android app, I am getting a list of nearby restaurants from Google Place API.
But unfortunately, this list does not give menus of the restaurant.
I have T_RESTAURANT and T_MENU tables.
Lets say, I get 4 restaurants in the list returned by API, then how should I make my query to extract data.
If I do:
SELECT name, votes, review FROM T_MENU WHERE restaurant_name = REST_NAME_1;
and I have to fire this query for each of the restaurants i.e. 4 times in this case.
Can anyone suggest me a good solution?
SELECT name,
votes,
review
FROM T_MENU
WHERE restaurant_name
IN ( <four restaurant names comma separated> )
You can use "IN" keyword instead of "=".
A also suggest using restaurant ids instead of names.
try this:
select T.name, T.votes, T.review ,M.<menu_items>
from T_RESTAURANT R join T_MENU M
where R.restaurant_name=T.restaurant_name

Query MySQL for rows that share a value, and returning them as columns?

This is for a homework assignment. I haven't copy-pasted the question below, I made an simpler version of it that focuses on the specific area where I'm stuck.
Let's say I have a table of two values: a person's name, and the place he had lunch yesterday. Assume everyone has lunch in pairs. How can I query the database to return all the pairs of people that had lunch together yesterday? Each pair must be only listed once.
I'm actually not even sure what the professor means by return them as pairs. I've sent him an email, but no reply yet. It seems like he wants me to write a query that returns a table with column 1 as person 1 and column 2 as person 2.
Any suggestions on how to go about this? Does it seem right to assume he wants them as separate columns?
So far, I basically have:
SELECT name, restaurant FROM lunches GROUP BY restaurant, name
which essentially just reorganizes the table so that the people who had lunch together are one after the other.
We have to assume there can be only one pair eating lunch in a given restaurant.
You can get a list of pairs either using self-join:
SELECT l1.name, l2.name FROM lunches l1
JOIN lunches l2
ON l1.restaurant = l2.restaurant AND l1.name < l2.name
or using GROUP BY:
SELECT GROUP_CONCAT(name) FROM lunches
GROUP BY restaurant
The first query will return pairs in two different columns, while the second in one column, using comma as separator (default for GROUP_CONCAT, you can change it to whatever you wish).
Also note that for the first query names in pairs will come in alphabetical order as we use < instead of <> to avoid listing each pair twice.

What is the best way to count rows in a mySQL complex table

I have a table with the following fields (for example);
id, reference, customerId.
Now, I often want to log an enquiry for a customer.. BUT, in some cases, I need to filter the enquiry based on the customers country... which is in the customer table..
id, Name, Country..for example
At the moment, my application shows 15 enquiries per page and I am SELECTing all enquiries, and for each one, checking the country field in customerTable based on the customerId to filter the country. I would also count the number of enquiries this way to find out the total number of enquiries and be able to display the page (Page 1 of 4).
As the database is growing, I am starting to notice a bit of lag, and I think my methodology is a bit flawed!
My first guess at how this should be done, is I can add the country to the enquiryTable. Problem solved, but does anyone else have a suggestion as to how this might be done? Because I don't like the idea of having to update each enquiry every time the country of a contact is changed.
Thanks in advance!
It looks to me like this data should be spread over 3 tables
customers
enquiries
countries
Then by using joins you can bring out the customer and country data and filter by either. Something like.....
SELECT
enquiries.enquiryid,
enquiries.enquiredetails,
customers.customerid,
customers.reference,
customers.countryid,
countries.name AS countryname
FROM
enquiries
INNER JOIN customers ON enquiries.customerid = customers.customerid
INNER JOIN countries ON customers.countryid = countries.countryid
WHERE countries.name='United Kingdom'
You should definitely be only touching the database once to do this.
Depending on how you are accessing your data you may be able to get a row count without issuing a second COUNT(*) query. You havent mentioned what programming language or data access strategy you have so difficult to be more helpful with the count. If you have no easy way of determining row count from within the data access layer of your code then you could use a stored procedure with an output parameter to give you the row count without making two round trips to the database. It all depends on your architecture, data access strategy and how close you are to your database.