How can i do something additional with this MySQL query? in php - php

$SQL = "
DELETE male_users from male_users
LEFT JOIN
(
select id from male_users order by date_time DESC LIMIT 0, 100
) t1
ON male_users.id=t1.id
where t1.id is null
";
if($row_male[0] > 100){
$result = $mysqli->query($SQL) or die($mysqli->error.__LINE__);
}
I'm using this query to delete all names in a list past the most recent 100.
However, each of the names have a URL of an image on the server associated with them. How can I use this query and actually get the names of each of the items its deleting into a for loop to delete their corresponding image URLs?
Typically I'd want to use unlink(URL)
With a join query such as this, how do I get the actual returned row usernames?

First SELECT to get all the image IDs, then run DELETE combined with WHERE IN, and also unlink each image.
Pseudo code would be:
SELECT image_id, image_path FROM table WHERE condition;
Fill the results into an array, then:
DELETE ... WHERE id IN (your ids) // (1, 2, 3, 5, 100)
Then loop the array, and for each do:
unlink($image_path);
You didn't show us your table structures, but that's roughly how you could do it. And don't forget you need image server path, not the url, for unlink.

Related

php pg_fetch_array only show first result

i query to check if a point(input) is intersect with polygons in php:
$sql1="SELECT ST_intersects((ST_SetSRID( ST_Point($startlng, $startlat),4326))
, zona_bahaya.geom) as intersek
FROM zona_bahaya";
$query1 = pg_query($conn,$sql1);
$check_location = pg_fetch_array($query1);
if (in_array('t',$check_location)) {
dosemthing1;}
else {dosomething2;}
it's work peroperly before i update the data
after data updated, it's only show the first row when i check the pg_fetch_array result. here is the result {"0":"f","intersek":"f"} .
i try to check from pgadmin and it's can show 8 result (1 true(intersected) and 7 false(not intersect)) using updated data with this query:
SELECT ST_intersects((ST_SetSRID( ST_Point(110.18898065505843, -7.9634510320131175),4326))
, zona_bahaya.geom) as intersek
FROM zona_bahaya;
to solve it, i order the query result descended so the 'true' gonna be the first like this:
order by intersek desc
anybody can help me to findout way it just only show the first row???
here some geom from STAsText(zonabahaya.geom) not all of them : MULTIPOLYGON(((110.790892426072 -8.19307615541514,110.791999687385 -8.19318330973567,110.794393723931 -8.1927980624753,110.794586347561 -8.19205508561603,110.795329324421 -8.19120203811094,110.796540101525 -8.19023891996003,110.797503219676 -8.18933083713203,110.798576408472 -8.18919324882476,110.79929186767 -8.18957849608512,110.800337538805 -8.19059664955894,110.800585197758 -8.19150473238694,110.80022746816 -8.19238529755349,110.799787185576 -8.19290813312112,110.799589319279 -8.19300706626968,110.798788231202 -8.19299429992581,110.798537293576 -8.19311976873883,110.79850269889 -8.1933090511224,110.798620939451 -8.19433728092441)))
In order to filter only the records that intersect you have to use ST_Intersects in the WHERE clause:
SELECT *
FROM zona_bahaya
WHERE ST_Intersects(ST_SetSRID(ST_Point(110.18, -7.96),4326),zona_bahaya.geom);
Since you're dealing with points and polygons, perhaps you should take a look also at ST_Contains.
In case you want to fetch only the first row you must set a limit in your query - either using LIMIT 1 or FETCH FIRST ROW ONLY -, but it would only make sense combined with a ORDER BY, e.g.
SELECT *
FROM zona_bahaya
JOIN points ON ST_Intersects(points.geom,zona_bahaya.geom)
ORDER BY gid
FETCH FIRST ROW ONLY;
Demo: db<>fiddle

Delete duplicate rows in MySQL using PHP script

I need a PHP function that deletes duplicate rows from MySQL database table. For example, I have a table like this:
I tried the following without success:
$find = mysql_query("SELECT * FROM users");
while ($row = mysql_fetch_assoc($find))
{
$find_1 = mysql_query("SELECT * FROM users ");
if (mysql_num_rows($find_1) > 0) {
mysql_query("DELETE FROM users WHERE ID =$row[num]");
}
I need to delete this duplicate rows and Keep only one of them only using PHP (and not my SQL database). Is there a way to do this?
You can do this with a single query, without a php loop (which, obviously, does not do what you want here):
delete t
from mytable t
inner join (select user, min(num) num from mytable group by user) t1
on t.user = t1.user and t.num > t1.num
This deletes rows that have the same user, while retaining the row with the smallest num.

How to count if value of a variable is repeated?

I am learning how to work with MySQL, and at the moment I succeed to show data from my table, using:
while($objResult2 = mysqli_fetch_assoc($objQuery_product)) {
Results are shown by using this variable $objResult2["id_product"]; this way i can take from DB any field I want like: $objResult2["name"]; $objResult2["email"]; etc.
But what i do if i have in the table more rows with the same id_product?
I want to write a if statment, which counts if id_product repeats. How to do that? If it is a lot of work, atleast please give me an idea of the right tutorial that I must read. Because i am trying second day to fix this, and searched google but i didnt find what i need, or maybe i coulndt understand it....
This is my query
$sql_product = "SELECT * FROM ps_product AS prod";
$join_product = " LEFT JOIN ps_product_lang AS lang ON lang.id_product = prod.id_product";
$join2_product = " LEFT JOIN ps_stock_available AS stok ON stok.id_product = prod.id_product";
$where_product =" WHERE prod.id_category_default = $idp AND lang.id_lang = 8";
$sql_product = $sql_product.$join_product.$join2_product.$where_product;
$objQuery_product = mysqli_query($objConnect, $sql_product) or die ("Error Query [".$sql_product."]");
You can simple remove the same id_product using DISTINCT keyword in your query. Such as:
SELECT DISTINCT id_product FROM my_table
This will give you results with different ids only.
The second way of doing it is taking the output values inside an array.
In your while loop:
$my_array[] = $objResult2["id_product"];
Then using array_filter remove all the duplicates inside the array.
YOu can also use array_count_values() if you want to count the duplicate values.
Ok here we go. For example you are fetching data with this query.
select id_product, name from PRODUCTS;
Suppose above query gives you 5 records.
id_product name
1 bat
2 hockey
2 hockey
3 shoes
4 gloves
Now you got 2,2 and hockey, hockey. Instead of thinking this way that you have to introduce an if statement to filter repeating records or same name or id_product records.
Rewrite your sql query like this.
select distinct id_product, name from PRODUCTS;
Or if you need count of each then my friend you will write your query something like this...
Graham Ritchie, if Andrei needs count of each repeating record then we will do something like this in our query.
SELECT PRODUCT_ID,
COUNT(PRODUCT_ID) AS Num_Of_Occurrences
FROM PRODUCTS
GROUP BY PRODUCT_ID
HAVING ( COUNT(PRODUCT_ID) > 1 );
SELECT id_product,COUNT(*) AS count
FROM tablename
GROUP BY id_product;
This query will then return you two items in your query
$objResult2["id_product"] //and
$objResult2["count"]
The if statement is then just
if($objResult2["count"] > 1){
//Do whatever you want to do with items with more than 1 occurence.
//for this example we will echo out all of the `product_id` that occur more than once.
echo $objResult2["id_product"] . " occurs more than once in the database<br/>";
}

Update values of database with values that are already in DB

I've a database that stores data read from different sensors. The table looks like this:
[SensorID][timestampMS][value]
[Sensor1][123420][10]
[Sensor1][123424][15]
[Sensor1][123428][6554]
[Sensor1][123429][20]
What I would like to do is the following: There are some reads that are corrupted (numbers that are 6554), and I would like to Update that with the next value that is not corrupted (in the example shown below that would be 20). So, if a number is 6554, I would like to update that with the next value (in timestamp), that is not corrupted.
I was thinking on doing this in PHP, but I wonder if it's possible to do it directly with a SQL script.
Appreciate :)
You can use a correlated sub-query...
UPDATE
myTable
SET
value = (SELECT value FROM myTable AS NextValue WHERE sensorID = myTable.SensorID AND timestampMS > myTable.timestampMS ORDER BY timestampMS ASC LIMIT 1)
WHERE
value = 6554
The sub-query gets all the following results, ordered by timestampMS and takes just the first one; That being the next value for that SensorID.
Note: If no "next" value exists, it will attempt to update with a value of NULL. To get around this, you can add this to the WHERE clause...
AND EXISTS (SELECT value FROM myTable AS NextValue WHERE sensorID = myTable.SensorID AND timestampMS > myTable.timestampMS ORDER BY timestampMS ASC LIMIT 1)
EDIT
Or, to be shorter, just use IFNULL(<sub_query>, value)...
Not sure if this is valid syntax, can't test it ATM. You may need to change this to be JOINs instead of the nested subqueries, but in concept you can do something like (for SQL Server):
UPDATE t1
SET Value = ( SELECT Value
from MyTable t2
WHERE t2.SensorID =t1.SensorID
AND t2.[timestamp] =
( SELECT MIN([TimeStamp])
FROM mytable t3
where t3.sensorid = t2.sensorID
AND t3.[timestamp] > t2.[timestamp]
)
)
FROM Mytable t1
WHERE t1.value = 6554
I did a workaround based on Dems solution, and it works in Mysql:
I've created a "copy" of the sensors table like this:
drop table if exists sensors_new;
create table if not exists sensors_new like sensors;
insert into sensors_new select * from sensors;
Then I do what Dems recommended me doing, but using this new aux table in the select (to avoid the error that Mysql launches when Updating a table while doing a select in the same table).
UPDATE
sensors
SET
raw_data = (SELECT raw_data FROM sensors_new AS NextValue WHERE sensor_id = sensors.sensor_id AND timestampMS > sensors.timestampMS ORDER BY timestampMS ASC LIMIT 1)
WHERE
value = 6554
Then, just drop this auxiliar table.
I hope this helps Mysql users.

Looping through data from multiple tables PHP/Mysql

HI all,
I am trying to figure out how to put this into words even, but I am wanting to know how to format the output from each table separately in a "multiple table" mysql query. The output from the table1 "wall" is formatted within a while loop, but the content from table2 "actions" is already formatted(as 1 line of text with links) before it is inserted into the table(column action_body), so inside the loop I would only be outputting the action_date and action_body columns from the actions table.
I am probably not using the correct sql method(if Im doing anything right at all, that is) for the results I need, so feel free to correct my novice example, or suggest a new way to approach this.
Query:
$query = "SELECT wall.wall_id, wall.wall_owner_id, wall.wall_user_id,
wall.wall_post_date, wall.wall_post_content, actions.action_id,
actions.action_date, actions.action_user_id, actions.action_title,
actions.action_body FROM wall, actions
ORDER BY wall.wall_post_date, actions.action_date DESC";
$result = mysql_query($query);
while( $rows = mysql_fetch_assoc($result) {
// What to put here
}
Any help is appreciated, thanks, Lea
Update after comments
SELECT w.* FROM (
(SELECT
'w' as type,
wall_id as id,
wall_owner_id as owner_id,
wall_user_id as user_id,
wall_post_date as post_date,
NULL as title,
wall_post_content as content
FROM wall
WHERE wall_owner_id = x # user id of owner
)
UNION
(SELECT
'a' as type,
action_id as id,
action_user_id as owner_id,
NULL as user_id,
action_post_date as post_date,
action_title as title,
action_body as content
FROM actions
WHERE action_user_id = x # user id of owner
)
) w
ORDER BY w.post_date DESC
Because you don't JOIN on a specific field, you're gonna get every row-row combination of the two tables, which is a whole lot more data than you probably want.
You'd be better of by doing 2 queries, one for each table. While looping through the result of each table, you can collect the data you want in one array, with the field you want to sort it by as array key.
Then you sort the array, and loop through it to print it out.

Categories