Selecting MySQL data rows with an int range - mysql

Alright, for starters I am not very experienced with mysql.
The situation is as following:
I have a data table with zip code records. I need a query that finds the correct row with a zip code and number, where the table has a number range, something like this.
Zipcode | NumberLower | NumberUpper | Street name
1234AB | 10 | 20 | Imaginary Drive
1234AB | 30 | 40 | Fantasy Street
7261XY | 2 | 4 | Rainbow Road
My current query is
SELECT * FROM zipcodetable WHERE zipcode="1234AB"
which returns the first two rows, as expected. What query should I use if I want to find the street name for the adress with zipcode 1234AB and number 34?

Add BETWEEN clause:
SELECT *
FROM zipcodetable
WHERE Zipcode='1234AB'
AND 34 BETWEEN NumberLower AND NumberUpper

Related

MySQL output most visited locations

I've got a table in a MySQL-database with thousands of checkins from my phone. Every x seconds, a new location is inserted.
This is how the table looks like:
+----+-----------+----------+------------+------------+
| id | lat | lon | date | timestamp |
+----+-----------+----------+------------+------------+
| 1 | 51.650586 | 5.622935 | 14-08-2018 | 1534233062 |
+----+-----------+----------+------------+------------+
| 2 | 51.65181 | 5.622228 | 14-08-2018 | 1534230962 |
+----+-----------+----------+------------+------------+
| 3 | 51.653715 | 5.6194 | 14-08-2018 | 1534230121 |
+----+-----------+----------+------------+------------+
Besides the GPS coordinates, date and timestamp I'm saving address data from the Google Maps Geocode API too, but street names aren't always right so it's not useful to use for data grouping.
I'm currently displaying the last inserted location on a Google Map using JavaScript, just as a single pointer. I'm looking for a MySQL-query that outputs a list of the 5 most visited locations for a defined date. There are a few hundred location check-ins a day.
It would be great if they could be grouped together, with a distance set of 500 meters. So for example, the 3 locations from above will be grouped together as the distance between them is less than 500 meters.
Could somebody help me writing a query for this? All help is highly appreciated.

Need help on SQL query - Select data with duplicate multiple data entries in one data field

I need to select all data having non-duplicate IDs..
here's my sample table..
----------------------------------------------------------------------------------
ID | Zip-Code | Search Query | ID_LIST
----------------------------------------------------------------------------------
1 | 1000 | Query Sample 1 | 13,14,15,
----------------------------------------------------------------------------------
2 | 2000 | Query Sample 2 | 16,13,17,
----------------------------------------------------------------------------------
3 | 3000 | Query Sample 3 | 18,17,13,
----------------------------------------------------------------------------------
4 | 4000 | Query Sample 4 | 15,16,17,18,
----------------------------------------------------------------------------------
5 | 5000 | Query Sample 5 | 19, 20,
u can notice that IDs 1 and 2 have duplicate, which is 13 on ID_LIST
2 and 3 also have duplicate, which is 13 and 17.
What I want to do is make it like this...
----------------------------------------------------------------------------------
ID | Zip-Code | Search Query | ID_LIST
----------------------------------------------------------------------------------
1 | 1000 | Query Sample 1 | 13,14,15,
----------------------------------------------------------------------------------
2 | 2000 | Query Sample 2 | 16,17,
----------------------------------------------------------------------------------
3 | 3000 | Query Sample 3 | 18,
----------------------------------------------------------------------------------
5 | 5000 | Query Sample 5 | 19,20,
What query would be good for this? Any Help?
Best way to approach it is to normalize your data, as mentioned in comments. But if you absolutely have to do it this way, it would be very difficult to do in query on mysql.
I would suggest you to create a procedure for it. As and when you develop each step, you can google that particular solution of that step, and test it and build up on that. Let me know if any step sound confusing/unclear.
Create a variable string, say v_vals. Initialize with null. At the end of procedure, it will contain all the distinct values of id_list (13,14...20)
Iterate through each row.
Count the number of comma in id_list.
Loop from 1 to number of comma.
In every iteration, use substring and instring to find position of each comma and then extract values from id_list. (13,14...)
use another variable v_id_list. Put null in it.
Search for the values (from step 5) in v_vals. If they exist in v_val, then skip them, else put them in v_val and v_id_list.
Now run an update statement to update id_list with v_id_list.
Now repeat Step 3 to 8 for each row.
Note that v_id_list will be reinitialize for each loop, however v_val will contain all the distinct values of id_list.

Efficiently join (and update) a table by value into a min/max value range

I have two tables that look like this:
IpNumbers
+----------+----------+-----------------------+
|____min___|____max___|__correspondingCountry_|
| | | |
| 0 | 10 | Australia |
| 11 | 20 | US |
| 21 | 30 | Taiwan |
|____31____|___40_____|_________Canada________|
Users
+----------+----------+----------------+
|__userId__|__ipNumber__|____country___|
| 1 | 6 | |
| 2 | 13 | |
| 3 | 7 | |
|____4_____|_____21_____|______________|
There are IpNumbers table which has a number derrived from an IP address - and this corresponds to a certain country the IP address belongs to. If the Ip Number is between 11 and 20 for example then the user with that IP Address is from the United States (US).
My problem: I have about 60,000 users in the Users table - each users has an IP number associated with them. I also have the IpNumbers table with about 4,000,000 records of Ip Number vs Country in it.
What is the most efficient SQL query I could construct to assign a Country to each user in the Users table? And how long could I expect the query to be completed in?
Note: I have indexed min and max columns in the ipNumbers table and I have also indexed userId column in the Users table. The userId field is also unique.
Edit: The ipNumber in the users table is also the derived integer value
This is a rather common problem. I think the best approach starts with an index on IpNumbers(min, max, corresponding_country). (The last column is not strictly necessary).
Then, you can use the following query:
select u.*,
(select ipn.corresponding_country
from IpNumbers ipn
where ipn.min <= u.ipNumber
order by ipn.min desc
limit 1
) as corresponding_country
from users u;
This should use the index for the where and the order by. However, it does not validate the end condition. If you need, you can use the same logic to get max out and then do a comparison to see if the ip address falls in the range.
Try as below:
SELECT u.USERID, u.IPNUMBER, i.CorrespondingCOUNTRY FROM USERS u, IPNUMBERS i
WHERE u.IPNUMBER BETWEEN i.MIN AND i.MAX
/

should I use MySQL procedure for this query?

I want to make stored procedure but I don't know what should be the right approach or if this is even possible to do in MySQL.
Let me introduce you with my problem. Let's say I have table that has columns like this:
TABLE A
id | Hotel | city_name | region_name | country
1 | A | Amsterdam | North-Holland | Netherlands
2 | B | Amsterdam | North-Holland | Netherlands
3 | C | Leiden | North-Holland | Netherlands
4 | D | Katwijk | North-Holland | Netherlands
5 | E | Leiden | North-Holland | Netherlands
6 | F | Katwijk | North-Holland | Netherlands
I would like to get only 3 results each time I execute this query and results need to be created in this order:
If there are 3 or more cities ( user selects in this case we can take Amsterdam ) that city_name=Amsterdam then return random 3 cities in Amsterdam
If there is less then 3 records in Amsterdam return any of the record that has Amsterdam + return random records where region=North-Holland but the total amount of the records that are returned should always be 3 ( example: we have 2 records where city= Amsterdam + we take one random record from region=North Holand;
example2: we have one record where city=Amsterdam + we take 2 random records where region="north Holland")
Is that possible to this with the SQL Or should I get all the records in php and then iterate through each of the records?
I probably need to pass 2 arguments in the procedure (city_name, region ).
So far I have tried some basic SQL queries and I couldn't get it to work.
You should try something like
(SELECT *
FROM A
WHERE city_name = 'Amsterdam'
ORDER BY RAND()
LIMIT 3)
UNION
(SELECT *
FROM A
WHERE region = 'North Holand' AND city_name <> 'Amsterdam'
ORDER BY RAND()
LIMIT 3)
LIMIT 3;
I would recommend you do the logical part of this primarily in php. While it is possible to do in sql, I've found that logic structures in sql tend to be hard to follow, and that is less of an issue in php.
Doing the logic in php could require two separate queries (but only if you don't get 3 initially).
I'd run a query to get the initial three (use LIMIT 3 in the sql). Check to see if you got three results. If you didn't, subtract the amount you do get from 3, then use that as the LIMIT in a second query to get the other random results.

Combine count rows in MySQL

I've got a table in MySQL that looks roughly like:
value | count
-------------
Fred | 7
FRED | 1
Roger | 3
roger | 1
That is, it was created with string ops outside of MySQL, so the values are case- and trailing-whitespace-sensitive.
I want it to look like:
value | count
-------------
Fred | 8
Roger | 4
That is, managed by MySQL, with value a primary key. It's not important which one (of "Fred" or "FRED") is kept.
I know how to do this in code. I also know how to generate a list of problem values (with a self-join). But I'd like to come up with a SQL update/delete to migrate my table, and I can't think of anything.
If I knew that no pair of records had variants of one value, with the same count (like ("Fred",4) and ("FRED",4)), then I think I can do it with a self-join to copy the counts, and then an update to remove the zeros. But I have no such guarantee.
Is there something simple I'm missing, or is this one of those cases where you just write a short function outside of the database?
Thanks!
As an example of how to obtain the results you are looking for with a SQL query alone:
SELECT UPPER(value) AS name, SUM(count) AS qty FROM table GROUP BY name;
If you make a new table to hold the correct values, you INSERT the above query to populate the new table as so:
INSERT INTO newtable (SELECT UPPER(value) AS name, SUM(count) AS qty FROM table GROUP BY name);
Strangely, MySQL seems to do this for you. I just tested this in MySQL 5.1.47:
create table c (value varchar(10), count int);
insert into c values ('Fred',7), ('FRED',1), ('Roger',3), ('roger',1);
select * from c;
+-------+-------+
| value | count |
+-------+-------+
| Fred | 7 |
| FRED | 1 |
| Roger | 3 |
| roger | 1 |
+-------+-------+
select value, sum(count) from c group by value;
+-------+------------+
| value | sum(count) |
+-------+------------+
| Fred | 8 |
| Roger | 4 |
+-------+------------+
I was surprised to see MySQL transform the strings like that, and I'm not sure I can explain why it did that. I was expecting to have to get four distinct rows, and to have to use some string functions to map the values to a canonical form.