Ip address compare in database - php

I am trying to solve a problem that could compare 2 columns in a table.
the table is as follows
------------------------------------------
| from | to | Country |
------------------------------------------
| 25.0.0.1 | 25.255.255.255 | denmark |
------------------------------------------
| 68.0.0.1 | 68.255.255.255 | USA |
My problem is i have a ip of 25.195.32.0 and i want to compare this to the from and to column and return the country name.

You can use INET_ATON to get a numeric value of the IPs to compare.
SELECT country FROM table
WHERE INET_ATON('25.195.32.0') BETWEEN INET_ATON(from) AND INET_ATON(to)
http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_inet-aton

You can find using IN() try condition according you use AND or OR
WHERE from IN('your_ip') OR to IN('your_ip')

select * from db.table
Then in php (assuming you've run the quest and stored results):
$lookupIP;
for($i=0;$i<$db->getRowCount();$i++) {
$partsFROM = explode(".", $FROM);
$partsTO = explode(".", $TO);
$partsLOOKUP = explode(".",$lookupIP);
if(
$partsLOOKUP[0] >= $partsFROM[0] && $partsLOOKUP[0] <= $partsTO[0]
&& $partsLOOKUP[1] >= $partsFROM[1] && $partsLOOKUP[1] <= $partsTO[1]
&& etc..
) return $Country
}
Not particularly efficient or elegant but you get the idea.

As i interpret from the question, you can use some mask and get the base ip address and then compare it. To use the mask and get base ip, you need to learn something about different classes (A, B, C, D) used from addressing.
Refer this link http://www.subnet-calculator.com/

INET_ATON gives desired solution on IPV4 addresses.
Apart from that, you can also try HEX version of the IP to compare in between.
SELECT HEX( input_ip_value )
BETWEEN HEX( from_ip_column )
AND HEX( to_ip_column )
Example:
mysql> select #i:=hex('25.195.32.0'),
-> #f:=hex('25.0.0.1'),
-> #t:=hex('25.255.255.255'),
-> #i between #f and #t is_between;
+------------------------+---------------------+------------------------------+------------+
| #i:=hex('25.195.32.0') | #f:=hex('25.0.0.1') | #t:=hex('25.255.255.255') | is_between |
+------------------------+---------------------+------------------------------+------------+
| 32352E3139352E33322E30 | 32352E302E302E31 | 32352E3235352E3235352E323535 | 1 |
+------------------------+---------------------+------------------------------+------------+

Select a range:
SELECT Country FROM table_name WHERE ip_address >= from AND to <= ip_address
If you can use a script (eg php) you could select the entire table and make a mask to the IP. Something like:
We can know what belongs to the network address 192.168.129.3/18 ip as
follows:
ip_en_binario = decbin (ip2long ("192.168.129.3"));
mascara_en_binario = decbin (ip2long ("255.255.192.0"));
resultado_en_binario $ = $ & $ mascara_en_binario ip_en_binario;
miss long2ip (bindec ($ resultado_en_binario));
The result returned us this script is 192.168.128.0, which is the network address to which the IP belongs 192.168.129.3/18.
Then, you can do a 'SELECT' of your network with "from" and "to" fields.

Transform IP into integer, then compare integer is simple. MySQL offers the inet_aton function to do so.
select Country from table_name where inet_aton($ip) between inet_aton(`from`) and inet_aton(`ip`);
For performance, you should transform column from, to to integer manully. eg. add to columns from_n, to_n. then your SQL will be like this:
select Country from table_name where inet_aton($ip) between `from_n` and `to_n`
If you are not using MySQL, you should transform $ip into integer $ip_n first (using something like Python's socket.inet_aton), then replace inet_aton($ip) with $ip_n.

use this query
select Country from table_name where from=to;

Related

SQL : Merge two rows by some ID and keep values

I'm facing a relatively easy problem but I can't manage to wrap my head around a solution. Keep in mind I'm using PHP with the Laravel framework if it can makes things any easier.
I have a table filled with data like so :
ID | TRANSACTION_ID | BEACON_TYPE
---+----------------+---------------
1 | 1 | "abc"
2 | 2 | "def"
3 | 2 | "xyz"
and I would like to group them by transaction ID and to keep the beacon type inside the data like so:
ID | TRANSACTION_ID | BEACON_TYPE
---+----------------+---------------
1 | 1 | "abc"
2 | 2 | "def", "xyz"
I've tried using group by with no avail. Any ideas or hints on how to accomplish that? As I said earlier there might be some way to do it with Laravel Eloquent.
Assuming you're using MySQL, the function you're looking for is GROUP_CONCAT(). Using Eloquent, it would look something like this:
$transactions = DB::table('tableName')
->select('TRANSACTION_ID', DB::raw('GROUP_CONCAT(BEACON_TYPE SEPARATOR ', ') as BEACON_TYPE'))
->groupBy('TRANSACTION_ID')
->get();
Note, if you want to change the separator, you just need to edit the ', ' to something else. The default separator is ','.
Use GROUP_CONCAT() to concatenate values of the group. Give it a SEPARATOR of ', ' to get the groups with comma separated values.
Your expected result is going to lose some information, since the IDs of the grouped row will be both 2 and 3 (in your example). So either don't select those IDs, or add them with a separate GROUP_CONCAT().
The raw SQL query would be using GROUP_CONCAT(). The following queries use the table foo, replace that with your actual table name.
SELECT TRANSACTION_ID,
GROUP_CONCAT(BEACON_TYPE SEPARATOR ', ') AS BEACON_TYPE
FROM foo
GROUP BY TRANSACTION_ID
Using Eloquent, you need to use DB::raw() to select the GROUP_CONCAT() part, as there's no Eloquent method for GROUP_CONCAT(), so then it becomes
$result = DB::table('foo')
->select('TRANSACTION_ID',
DB::raw("GROUP_CONCAT(BEACON_TYPE SEPARATOR ', '") as BEACON_TYPE)
->groupBy('TRANSACTION_ID');
or if you want to include the grouped IDs to, then..
$result = DB::table('foo')
->select('TRANSACTION_ID',
DB::raw("GROUP_CONCAT(BEACON_TYPE SEPARATOR ', '") as BEACON_TYPE),
DB::raw("GROUP_CONCAT(ID SEPARATOR ', '") as ID)
->groupBy('TRANSACTION_ID');
If you already have the data from the database and just want to use collection functions you can do the following:
$things = $things->groupBy('TRANSACTION_ID')
->map(function($x) {
$beaconTypes = $x->implode('BEACON_TYPE', ', ');
$firstThing = $x->first();
$firstThing['BEACON_TYPE'] = $beaconTypes;
return $firstThing;
});

Codeigniter - How to select row id's of matching date column in query

I am trying to write a query that outputs the shiftId's into an array.
I have a table that looks like this.
+---------+----------+-------+
| shiftId | endTime | shift |
+---------+----------+-------+
| 1 | 03/03/19 | 1 |
| 2 | 03/03/19 | 2 |
| 3 | 03/01/19 | 1 |
| 4 | 03/01/19 | 2 |
+---------+----------+-------+
I want to return the shiftId of each date with the largest shift, and not sure how to go about.
I want my array to look like below, based on above table.
Array
(
[0] => 2
[1] => 4
)
I have tried to group_by date and then select_max of each shift but don't think I'm on the correct path. Any help would be appreciated.
I want to select shiftId foreach date where shift # is the largest.
You were on the right path!
Either use (this shows the SQL more clearly):
$query = $this->db->query('SELECT max(shiftId) shiftId FROM yourtable GROUP BY endTime')->result_array();
Or (if you want to use CI's query builder):
$query = $this->db->select_max('shiftId')->group_by('endTime')->get('yourtable')->result_array();
Both of these group the table by endTime, and then return the maximum shiftId for each group of identical endTimes. Both give an array that looks like this:
Array
(
[0] => Array
(
[shiftId] => 2
)
[1] => Array
(
[shiftId] => 4
)
)
To get rid of the shiftId index in the result and get the exact array structure from your OP, use:
array_column($query, 'shiftId');
Edit
If you want to get the shiftId for each endTime + MAX(shift) combination, use this:
SELECT shiftId FROM yourtable
WHERE CONCAT(endTime, "-", shift) IN (
SELECT CONCAT(endTime, "-", MAX(shift)) FROM yourtable GROUP BY endTime
)
The inner query (after IN) does more or less the same as the previous query: it groups the records in the table by endTime, then gets the maximum shift for each group of identical endTimes, and here it concatenates this with the endTime and a dash.
You need to concatenate endTime with MAX(shift) here, because MAX(shift) alone is not unique in the table (there's more than one shift with number 2, for example), and neither is endTime.
The outer query (SELECT shiftId...) then finds the matching shiftId for each endTime + MAX(shift) combination and returns that.
You need to use two (nested) queries for this, because the inner one uses grouping and the outer one doesn't, and you're not allowed to mix those two types in one query.
Note: CONCAT only works in MySQL, if you're using a different database type, you might have to look up what concatenation syntax it uses (could be + or || for example).
In CI:
$query = $this->db->query('SELECT shiftId FROM yourtable
WHERE CONCAT(endTime, "-", shift) IN (SELECT CONCAT(endTime, "-", MAX(shift)) FROM yourtable GROUP BY endTime)')->result_array();

php explode like function in mysql

I have a column in my database name location which have city name and country name in this format New york,America. I want to run a select query with the explode function like which we use in php to separate values like this
so that i can get comma , separated values
select explode(",",location) from address;
Also with the alias of city column holding New York and alias of country holding value of America. So that i can use them in my store procedure and insert this values in references table in the columns city and country
You can not really "explode" or split on all comma's, but you can split a string on any comma using SUBSTRING_INDEX.
SELECT SUBSTRING_INDEX('New york,America', ',', 1);
-> New york
Use Group concat
SELECT GROUP_CONCAT( location )
FROM `address`
CREATE FUNCTION strSplit(x varchar(255), delim varchar(12), pos int)
returns varchar(255)
return replace(substring(
substring_index(x, delim, pos+1),
length(substring_index(x, delim, pos)) + 1
), delim, '');
select strSplit("aaa,b,cc,d", ',', 1) as second;
> b
You can also select the row and store it as a string, and use the explode function to separate the values if you are intending to use the function itself.
Assuming that exploding will be to create N number of rows, then you can do it like this.
SET #completeString = "Hola,New york,America,!,";
SET #divider = ",";
WITH RECURSIVE strings(m) AS (
SELECT
#completeString
UNION ALL
SELECT
SUBSTRING(m, INSTR(m, #divider)+ 1)
FROM
strings
WHERE
INSTR(m, #divider)!= 0
)
SELECT
SUBSTRING_INDEX(m, #divider, 1) exploted_strings
FROM
strings;
That'll give you five rows, including the empty string
+----------------+
|exploted_strings|
+----------------+
| Hola |
| New york |
| America |
| ! |
| |
+----------------+
Or have it in a Procedure.
CREATE PROCEDURE explode(IN completeString TEXT, IN divider TEXT)
BEGIN
WITH RECURSIVE strings(m) AS (
SELECT
completeString
UNION ALL
SELECT
SUBSTRING(m, INSTR(m, divider)+ 1)
FROM
strings
WHERE
INSTR(m, divider)!= 0
)
SELECT
SUBSTRING_INDEX(m, divider, 1)
FROM strings;
END
And call it like
CALL explode ("Hola,New york,America,!,",",");

MySQL Select from 3 tables and get attendance In and Out Time for all Members in specific date

I have three table Like this:
members_tbl
id | Fullname | Email | MobileNo
attendance_in_tbl
id | member_id | DateTimeIN
attendance_out_tbl
id | member_id | DateTime_OUT
I want to select all members for date: 2014-03-10 by this query:
SELECT
attendance_in.EDatetime,
members_info.mfullname,
attendance_out.ODatetime
FROM
attendance_in
LEFT JOIN members_info ON members_info.id = attendance_in.MemID
LEFT JOIN attendance_out ON attendance_out.MemID = attendance_in.MemID
WHERE date(attendance_in.EDatetime) OR date(attendance_out.ODatetime) = "2014-03-10"
But it give me different results in Attendace_out Results
You have a mistake in your query.
You wrote:
WHERE date(attendance_in.EDatetime) /* wrong! */
OR date(attendance_out.ODatetime) = "2014-03-10"
This is wrong, as the first expression date(attendance_in.EDatetime) always evaluates to true.
You may want
WHERE date(attendance_in.EDatetime) = "2014-03-10"
OR date(attendance_out.ODatetime) = "2014-03-10"
But, this is guaranteed to perform poorly when your attendance_in and attendance_out tables get large, because it will have to scan them; it can't use an index.
You may find that it performs better to write this:
WHERE (attendance_in.EDatetime >='2014-03-10' AND
attendance_in.EDatetime < '2014-03-10' + INTERVAL 1 DAY)
OR (attendance_out.EDatetime >='2014-03-10' AND
attendance_out.EDatetime < '2014-03-10' + INTERVAL 1 DAY)
That will check whether either the checkin our checkout time occurs on the day in question.

Find a string inside the column name using MySQL query

I'm trying to write a select query for searching string in the particular column.
For example :
+----+------+-------------------------------+
| id | name | alternate |
+----+------+-------------------------------+
| 1 | Test | Test,Tests,test,tests,te,test |
| 2 | Demo | Demo.demo,dem,Dem |
+----+------+-------------------------------+
etc...
I just want to write a query for checking the submitted value name in the column name alternate
For example : I will submit the name test and it should check exists or not with the column name alternate that contains
use FIND_IN_SET()
$query = SELECT * FROM tablename WHERE FIND_IN_SET('test', alternate);
if(mysql_num_rows($query) > 0){
//if test was found
} else {
// test not found
}
for more information here
Try this query in mysql:
SELECT ID,NAME,ALTERNATE,
CASE WHEN (FIND_IN_SET(name, alternate) > 0)
THEN 'TRUE' ELSE 'FALSE' END RESULT FROM TABLE1;
SQL Fiddle
try this
select count(*) as total from tablename where alternate LIKE %test%
if the total value returned is greater than zero then string test exist in alternate column
One way of doing it is using the String function INSTR to check whether the Substring exists in the String or not. You can even pass a variable in Substring and String to check.
SELECT IF(INSTR(alternate,'test')! = 0,'Exists', 'Not Exists') as SearchResult FROM table;
Documentation can be found at:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_instr

Categories