I have a source table with these columns:
I also have a destination table like this:
The destination table has 1440 rows, with the minute column filled in (1 row for each minute in the day).
For each row in the source table, I need to fill in a "1" in the destination table for the appropriate channel (there are 10 channels total), for every minute between the StartTime and FinishTime.
I'm just doing this in MySQL Workbench (it's a one-time query). What is my beast approach?
Thanks,
-Scott
Pseudo-code:
SELECT DISTINCT ChannelNumber
FROM source
while ($row = fetch_assoc()) {
$channel_col = 'ch'.$row['ChannelNumber']
$sql = "
UPDATE destination
JOIN source ON StartTime = destination.minutes
AND source.ChannelNumber = $row[ChannelNumber]
SET destination.$channel_col = 1
";
query($sql);
}
Normally you have to be concerned about dynamically creating a string which becomes an SQL query to avoid SQL injection, but since all the data is coming from within your database it shouldn't be a problem.
Here is an MySQL solution:
CREATE PROCEDURE PopulateDestinationTable()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE n INT DEFAULT 0;
DECLARE CNumber INT DEFAULT 0;
DECLARE STime INT DEFAULT 0;
DECLARE FTime INT DEFAULT 0;
SELECT COUNT(*) FROM SourceTable INTO n;
SET i = 0;
WHILE i < n DO
SELECT ChanelNumber FROM SourceTable LIMIT i, 1 INTO CNumber;
SELECT StartTime FROM SourceTable LIMIT i, 1 INTO STime;
SELECT FinishTime FROM SourceTable LIMIT i, 1 INTO FTime;
SET #stat1 = CONCAT('UPDATE DestinationTable
SET ', CONCAT('Ch', CNumber), ' = 1 WHERE minutes BETWEEN ? AND ?');
PREPARE statement FROM #stat1;
SET #p1 = STime;
SET #p2 = FTime;
EXECUTE statement USING #p1, #p2;
SET i = i + 1;
END WHILE;
END$$
P.S. Don't forget to change Delimiter when create stored procedure :)
I modified the PHP code from #peter-bowers to this and got it to work:
<?php
$mysqli = new mysqli("ip", "user", "pass", "db");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
echo $mysqli->host_info . "\n";
$res = $mysqli->query("update scott_test set Ch1 = null, Ch2 = null, Ch3 = null, Ch4 = null, Ch5 = null, Ch6 = null, Ch7 = null, Ch8 = null, Ch9 = null, Ch10 = null");
$res = $mysqli->query("SELECT TIMESTAMPDIFF(MINUTE,DATE(TimeReceived),TimeReceived) AS StartTime,
CEIL(FaxDuration/60)+ TIMESTAMPDIFF(MINUTE,DATE(TimeReceived),TimeReceived) AS FinishTime,
ChannelNumber
FROM
fax_received
WHERE
DATE(TimeReceived) = DATE((NOW() - INTERVAL 3 DAY))");
while ($row = $res->fetch_assoc()) {
$channel_col = 'ch'.$row['ChannelNumber'];
$start_min = $row['StartTime'];
$end_min = $row['FinishTime'];
$sql = "UPDATE scott_test
SET $channel_col = 1
WHERE minutes between ($start_min, $end_min);
$mysqli->query($sql);
}
?>
Related
I have these two queries which work, but they are slow as can be. What is faster, or rather fastest way of doing this?
method 1)
$query = "
UPDATE list_data_extra
INNER JOIN list_data
ON (list_data_extra.serial_no = list_data.serial_no)
SET
list_data_extra.id = list_data.id,
list_data_extra.cid = list_data.cid,
list_data_extra.first = list_data.first,
list_data_extra.last = list_data.last,
list_data_extra.tracking_number = list_data.tracking_number
WHERE list_data_extra.id='0' AND list_data_extra.cid='0'
";
method 2)
$query = "UPDATE list_data_extra
INNER JOIN list_data USING (serial_no)
SET list_data_extra.id = list_data.id,
list_data_extra.cid = list_data.cid,
list_data_extra.first = list_data.first,
list_data_extra.last = list_data.last,
list_data_extra.tracking_number = list_data.tracking_number
WHERE list_data_extra.id='0'
AND list_data_extra.cid='0'";
Not sure this other method would be faster:
method 3)
$query="SELECT * FROM list_data_extra WHERE id='0' AND cid='0'";
$result=mysql_query($query);
$num_rows = mysql_num_rows($result);
if ($num_rows > 0) {
while($row=mysql_fetch_array($result)) {
$querytwo = mysql_fetch_array(mysql_query(
"SELECT id, cid, first, last, tracking_number
FROM list_data
WHERE serial_no='".$row['serial_no']."'"), MYSQL_ASSOC);
$querythree = "UPDATE list_data_extra
SET id='".$querytwo["id"]."', cid='".$querytwo["cid"]."',
first='".$querytwo["first"]."', last='".$querytwo["last"]."',
tracking_number='".$querytwo["tracking_number"]."'";
mysql_query($querythree);
}
}
Another thing i tried is this, which is building entire query then executing it all at once, which is a bit faster than above, but still slow as junk. the above is like 9 minutes per 1000 records and this here below is like 5 minutes per 1000.
method 4)
$query="SELECT * FROM list_data_extra WHERE id='0' AND cid='0'";
$result=mysql_query($query);
$num_rows = mysql_num_rows($result);
if ($num_rows > 0) {
$id_loop = "";
$cid_loop = "";
$first_loop = "";
$last_loop = "";
$trackingnumber_loop = "";
$listids = "";
while($row=mysql_fetch_array($result)) {
$querytwo = mysql_fetch_array(mysql_query("SELECT id, cid, first, last, tracking_number FROM list_data WHERE serial_no='".$row['serial_no']."'"), MYSQL_ASSOC);
$id_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["id"]."' ";
$cid_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["cid"]."' ";
$first_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["first"]."' ";
$last_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["last"]."' ";
$trackingnumber_loop .= "WHEN ".$row['listid']." THEN '".$querytwo["tracking_number"]."' ";
$listids .= ", ".$row['listid'];
}
$listidsb = substr($listids, 2);
$querythree = "UPDATE list_data_extra
SET
id = CASE listid
".$id_loop."
END,
cid = CASE listid
".$cid_loop."
END,
first = CASE listid
".$first_loop."
END,
last = CASE listid
".$last_loop."
END,
tracking_number = CASE listid
".$trackingnumber_loop."
END
WHERE listid IN (".$listidsb.")";
mysql_query($querythree) or die(mysql_error());
}
Is there a better and faster way to update multiple columns in many records in one table with data from another table?
CREATE TABLE list_data (
id int(11) NOT NULL AUTO_INCREMENT,
cid int(11) NOT NULL,
first varchar(255) NOT NULL,
last varchar(255) NOT NULL,
tracking_number varchar(255) NOT NULL,
serial_no varchar(9) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM AUTO_INCREMENT=555555 DEFAULT CHARSET=latin1
Unindexed JOIN and WHERE conditions can be slow, especially if they involve string data; try running these two (they make take a little time to run if the tables are large), and then trying your original query again.
ALTER TABLE list_data
ADD INDEX serial_idx (serial_no);
ALTER TABLE list_data_extra
ADD INDEX serial_idx (serial_no);
I have this following code in PHP and I want to convert this into MySQL stored procedure. I do not want to check on duplication error at db level error code due to the requirement of the application, it has to be done the same way as is done in PHP.
$sql2 = "SELECT zip__ID FROM zip WHERE zip_code='" . $zip . "' ";
$result2 = mysql_query($sql2);
if (mysql_num_rows($result2) == 0) {
$sql3 = "INSERT INTO zips SET zip_code='" . ($zip) . "'";
mysql_query($sql3);
$newZip = mysql_insert_id();
} else {
$row2 = mysql_fetch_array($result2);
$newZip = $row2['zip_id'];
}
//Update: May 6, 2015.
I have total 6 tables.
Table 1 contains fields like zip, city, state, country. This is in varchar format.
|ID|ZIP|CITY|STATE|COUNTRY|
|1|33430|Fort Lauderdale|FL|USA
There are four more tables that are:
Table 2: zips (id,zip_code)
Table 3: cities (id,city_name)
Table 4: state (id,state_name)
Table 5: countries (id,country_name)
I want to insert the date from table 1 into table 6, which is the replica of table 1. The only difference is that in Table 6, I want to insert IDs of the data in table 1. Hence, for every insertion to be made in Table 6, I have to run a query in the 4 tables (2,3,4 and 5). For instance, if the zip code in Table 1 is 33430 and it does not exist in Table 2, first I need to insert it, get its ID and then insert in Table 6.
I have to do the same for all fields in Table 1.
So if I do it in PHP, what I will do it:
$sql = "SELECT * FROM Table1";
$result = mysql_query($sql);
while($row=mysql_fetch_array($result){
$zip = $row['zip'];
$city = $row['city'];
$state = $row['state'];
$country = $row['country'];
//Process zip code
$sql2 = "SELECT zip_id FROM zips WHERE zip_code='" . $zip . "' ";
$result2 = mysql_query($sql2);
if (mysql_num_rows($result2) == 0) {
$sql3 = "INSERT INTO zips SET zip_code='" . ($zip) . "'";
mysql_query($sql3);
$newZip = mysql_insert_id();
} else {
$row2 = mysql_fetch_array($result2);
$newZip = $row2['zip_id'];
}
mysql_free_result($result2);
//Process city
$sql2 = "SELECT city_id FROM cities WHERE city_name='" . $city . "' ";
$result2 = mysql_query($sql2);
if (mysql_num_rows($result2) == 0) {
$sql3 = "INSERT INTO cities SET city_name='" . ($city) . "'";
mysql_query($sql3);
$newCity = mysql_insert_id();
} else {
$row2 = mysql_fetch_array($result2);
$newCity = $row2['city_id'];
}
mysql_free_result($result2);
//process other two tables......
}mysql_free_result($result);
I'm no MySQL expert either, but this is what I could find. You have to check out the syntax though. But I want to stress this. I Googled 2 sources, and I typed this out for you. If I could do it, I'm sure you could've done it as well.
CREATE PROCEDURE UpdateTable6()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE i, a, b, c, d INT;
DECLARE va, vb, vc, vd CHAR(<yourmax>);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE cur1 CURSOR FOR SELECT id, zip, city, state, country FROM table1;
OPEN cur1;
read_loop: LOOP
FETCH cut1 into i, va, vb, vc, vd;
IF done THEN
LEAVE read_loop;
END IF;
--REPEAT THIS FOR ALL 4 TABLES
IF (SELECT 1 = 1 FROM Table2 WHERE zip_code=va) THEN
BEGIN
SELECT a = TableID FROM Table2 WHERE zip_code=va;
END;
ELSE
BEGIN
INSERT INTO Table2 (zip_code) VALUES(va);
SELECT a = LAST_INSERT_ID();
END;
END IF;
--CHECK DETAILS IN TABLE6
IF (SELECT 1 = 1 FROM Table6 WHERE id=i) THEN
BEGIN
UPDATE TABLE6 set zip_id = a, city_id = b, state_id = c, country_id = d where id = i
END;
ELSE
BEGIN
INSERT INTO Table6 (zip_id, city_id, state_id, country_id ) VALUES(a, b, c, d);
END;
END IF;
END LOOP;
CLOSE cur1;
END;
My source where https://dev.mysql.com/doc/refman/5.0/en/cursors.html
I have a jersey java server and a mysql server:
I send a POST with an ArrayList<Long> to the server. Then I want to do a select like ...where long OR long OR long....
Is there an elegant way to solve this problem and not to do always a single select in a for loop?
How can I form a sql-statement with dynamic count of where clauses?
Thank you very mutch.
Instead of OR multiple times, you can use IN with the where clause in the SQL query.
You can read ArrayList object in a loop and set the where clause values.
JAVA code snippet:
int paramCount = list.size();
StringBuilder sqlSelect = new StringBuilder( 1024 );
sqlSelect.append( "select x,y,z from my_table " );
if( paramCount > 0 ) {
sqlSelect.append( "where long_column in ( " );
for( i = 0; i < paramCount; i++ ) {
sqlSelect.append( ( i > 0 ? ", ?" : "?" );
} // for each param
sqlSelect.append( " )" );
} // if list is not empty
// make the prepare statement (pst) with the above sql string
// ...
// now set the parameter values in the query
int paramIndex = 1;
if( paramCount > 0 ) {
for( i = 0; i < paramCount; i++ ) {
pst.setLong( paramIndex++, ( (Long)list.get( i ) ).longValue() );
} // for each param
} // if list is not empty
session_start();
if(!$_SESSION['user_id'])
{
$_SESSION['user_id'] = rand(1, 1000000);
include 'database_connect.php';
mysql_query('INSERT INTO product_views (user_session_id)
VALUES
('.$_SESSION['user_id'].')');
}
$productid = $_GET['name'];
$query = 'SELECT * FROM product_views WHERE user_session_id = '.$_SESSION['user_id'].'';
$result = mysql_query($query);
while ($row = mysql_fetch_array($result))
{
mysql_query('UPDATE product_views SET modelNumber="'.$productid.'" WHERE user_session_id="'.$_SESSION['user_id'].'"');
}
My field modelNumber is set to null, and I am performing an Update via the last query.
Do you think that since the default value is null, it is therefore not allowing an insertion?
My table structure:
CREATE TABLE `product_views` (
`id` int(10) DEFAULT NULL,
`user_session_id` int(11) DEFAULT NULL,
`product_id` varchar(100) DEFAULT NULL,
`view_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modelNumber` varchar(...
I'm confused:
$query = 'SELECT * FROM product_views WHERE user_session_id = '.$_SESSION['user_id'].'';
$result = mysql_query($query);
while ($row = mysql_fetch_array($result))
{
mysql_query('UPDATE product_views SET modelNumber="'.$productid.'" WHERE user_session_id="'.$_SESSION['user_id'].'"');
}
Why are you looping through this result set if you're not even using $row?
Edit: I think this is what you're really trying to do:
session_start();
if(!$_SESSION['user_id'])
{
// Get the user ID
$_SESSION['user_id'] = rand(1, 1000000);
require_once('database_connect.php');
// Get the model number and escape it to prevent SQL injection
$model_number = mysql_real_escape_string($_GET['name']);
// Insert a row that associates the user_id with the model number
mysql_query("INSERT INTO product_views (user_session_id,modelNumber) VALUES('{$_SESSION['user_id']}', '$model_number')");
}
So I have 3 DB tables that are all identical in every way (data is different) except the name of the table. I did this so I could use one piece of code with a switch like so:
function disp_bestof($atts) {
extract(shortcode_atts(array(
'topic' => ''
), $atts));
$connect = mysql_connect("localhost","foo","bar");
if (!$connect) { die('Could not connect: ' . mysql_error()); }
switch ($topic) {
case "attorneys":
$bestof_query = "SELECT * FROM attorneys p JOIN (awards a, categories c, awardLevels l) ON (a.id = p.id AND c.id = a.category AND l.id = a.level) ORDER BY a.category, a.level ASC";
$category_query = "SELECT * FROM categories";
$db = mysql_select_db('roanoke_BestOf_TopAttorneys');
$query = mysql_query($bestof_query);
$categoryQuery = mysql_query($category_query);
break;
case "physicians":
$bestof_query = "SELECT * FROM physicians p JOIN (awards a, categories c, awardLevels l) ON (a.id = p.id AND c.id = a.category AND l.id = a.level) ORDER BY a.category, a.level ASC";
$category_query = "SELECT * FROM categories";
$db = mysql_select_db('roanoke_BestOf_TopDocs');
$query = mysql_query($bestof_query);
$categoryQuery = mysql_query($category_query);
break;
case "dining":
$bestof_query = "SELECT * FROM restaurants p JOIN (awards a, categories c, awardLevels l) ON (a.id = p.id AND c.id = a.category AND l.id = a.level) ORDER BY a.category, a.level ASC";
$category_query = "SELECT * FROM categories";
$db = mysql_select_db('roanoke_BestOf_DiningAwards');
$query = mysql_query($bestof_query);
$categoryQuery = mysql_query($category_query);
break;
default:
$bestof_query = "switch on $best did not match required case(s)";
break;
}
$category = '';
while( $result = mysql_fetch_array($query) ) {
if( $result['category'] != $category ) {
$category = $result['category'];
//echo "<div class\"category\">";
$bestof_content .= "<h2>".$category."</h2>\n";
//echo "<ul>";
Now, this whole thing works PERFECT for the first two cases, but the third one "dining" breaks with this error:
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource ... on line 78
Line 78 is the while() at the bottom. I have checked and double checked and can't figure what the problem is. Here's the DB structure for 'restaurants':
CREATE TABLE `restaurants` (
`id` int(10) NOT NULL auto_increment,
`restaurant` varchar(255) default NULL,
`address1` varchar(255) default NULL,
`address2` varchar(255) default NULL,
`city` varchar(255) default NULL,
`state` varchar(255) default NULL,
`zip` double default NULL,
`phone` double default NULL,
`URI` varchar(255) default NULL,
`neighborhood` varchar(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=249 DEFAULT CHARSET=utf8
Does anyone see what I'm doing wrong here? I'm passing "dining" to the function and as I said before, the first two cases in the switch work fine.
I'm sure it's something stupid...
You should always initialize the variable you use to some (null) value and then check for it before using it. My guess is that your third case (dining) never gets executed because of some misspelled identifier or something. This causes default: to run, after which your while() will execute anyway. However, $query is not set to anything useful.
Therefore, you should throw an exception or otherwise break execution in the default: handler. Or, you may initialize $query = null; before the switch() and only do the while() loop when $query !== null.
On a related note: you might code more efficient when you instead use the following (note the exception handler):
$db_name = null;
$table = null;
switch ($topic) {
case "attorneys":
$db_name = 'roanoke_BestOf_TopAttorneys';
$table = 'attorneys'
break;
case "physicians":
$db_name = 'roanoke_BestOf_TopDocs';
$table = 'physicians'
break;
case "dining":
$db_name = 'roanoke_BestOf_DiningAwards';
$table = 'restaurants'
break;
default:
throw new Exception("Unknown topic.");
break;
}
$bestof_query = "SELECT * FROM $table p JOIN (awards a, categories c, awardLevels l) ON (a.id = p.id AND c.id = a.category AND l.id = a.level) ORDER BY a.category, a.level ASC";
$category_query = "SELECT * FROM categories";
$db = mysql_select_db($db_name);
$query = mysql_query($bestof_query);
$categoryQuery = mysql_query($category_query);
You're getting a sql error on that query. You should echo your mysql error and review it to fix your query. The warning you're getting is because you're passing a boolean false to mysql_fetch_assoc() which is expecting a result set. mysql_query() returns false if there is an error.
Look at your query code - you run $bestof_query regardless of whether it has been set to valid SQL. My first guess is that you're misspelling 'dining' somewhere and getting the default case.
Also, double check that your database names are correct (they are fairly complicated) and that all databases have the same permissions. Are you checking whether $db is true?