I'm perplexed, here is what I have.
Two tables, one is temporary, one is permanent.
table Temptable:
city , state //- has a list of 20 citys and states
table Permtable:
city , state //- has hundreds of citys and states
I want to do two things:
I want to use city and state from Temptable and query the Permtable to see if it already contains
that city and state. If it doesn't I want it to add it.
IF it has a match in city and state, I want it to play c:\sound.wav and then I want it add it to the
permtable.
I am lost as to how to do this.
This will tell you which records exist or don't exist from your TempTable:
SELECT T.City, T.State, CASE WHEN P.State IS NULL THEN 'DOES NOT EXIST' ELSE 'DOES EXIST' END
FROM TempTable T
LEFT JOIN PermTable P ON T.City = P.City AND T.STate = P.State
You can INSERT those records that don't exists in the PermTable like such:
INSERT INTO PermTable
SELECT T.City, T.State
FROM TempTable T
LEFT JOIN PermTable P ON T.City = P.City AND T.STate = P.State
WHERE P.State IS NULL
Not sure about your requirement to play a sound and it doesn't make sense to then add it (since it already exists).
Since we have no code to run with here, query temptable for city and state, then query SELECT COUNT(id) FROM permtable WHERE city='$tempcity' AND state='$tempstate'.
Then user mysqli_num_rows on your query to see if any matches were found.
$q= "SELECT COUNT(*) FROM temptable WHERE city='$tempcity' AND state='$tempstate'";
$r = #mysqli_query($dbc, $q);
if(mysqli_num_rows($r) != 0) {
echo "<embed src =\"sound.wav\" hidden=\"true\" autostart=\"true\"></embed>";
}
else {
//Do your other stuff.
}
It really depends on how you have your table set up. If you have column 'State' and column 'City' where 'City' is something like 'Dallas-Austin-Houstin-San Antonio' then you will have to query for 'State', explode the value of 'City' into an array, run a while to check for $tempcity in the array, which would look like the following:
$q = "SELECT city FROM permtable WHERE state='$tempstate'";
$r = #mysqli_query($dbc, $q);
$row = mysqli_fetch_array($r, MYSQLI_ASSOC);
if (mysqli_num_rows($r) == 1) { //STATE MATCH
$cityCheck = explode("-", $row['city']);
$i = 0;
$count = count($cityCheck);
$goodMatch = 0;
while ($i < $count) { //find out if user already voted on post
if ($cityCheck[$i] == $tempcity) {
$goodMatch = 1;
} //City State match
else { } //City does not match with state, continue while loop.
$i++;
} //END WHILE
else { } //STATE DID NOT MATCH
if ($goodmatch) {
echo "<embed src =\"sound.wav\" hidden=\"true\" autostart=\"true\"></embed>";
}
else {}
Related
I am trying to obtain results for a given member where status is pending or accepted doing the below:
$status1 = "Pending";
$status2 = "Attended";
$query = $conn->prepare('SELECT * FROM members WHERE member_id=:mID AND status=:status1 OR status=:status2');
$query->execute(array(':mID' => $mID,':status1' => $status1, ':status2' => $status2));
if ($query->rowCount() > 0) {
//start to create my table
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
//create variable, loop through and fill the table etc
}
}else{
echo "something";
}
This displays data - however, it even obtains results not specific to the member id (mID). Meaning other members data too!
I'm clearly missing something and or my query is wrong but struggling to find anything..
Any help appreciated.
You need to look at operator precedence for your database. You're doing this:
SELECT * FROM members WHERE member_id = :mID AND status = :status1 OR status = :status2;
Which most likely results in this:
SELECT * FROM members WHERE (member_id = :mID AND status = :status1) OR status = :status2;
But that's not what you want, so you will have to explicitly use parens like this:
SELECT * FROM members WHERE member_id = :mID AND (status = :status1 OR status = :status2);
Alternatively, you can use IN so that there's no OR:
SELECT * FROM members WHERE member_id = :mID AND status IN (:status1, :status2);
I have the following SELECT statement which SHOULD be returning the recordset ORDERED BY Last Name and it is not. I have checked to see if any blank characters/spaces are in the last name field and there isn't as they have all been trimmed using $last_name = trim(filter_input(INPUT_POST, 'LastName', FILTER_SANITIZE_STRING));.
$query_PaidOrders = "SELECT * FROM `orders` WHERE `payment_received` = '1'";
$rs_PaidOrders=$conn->query($query_PaidOrders);
if($rs_PaidOrders === false){
trigger_error('SQL error:'.$query_PaidOrders.' Error: '.$conn->error, E_USER_ERROR);
}
else{
while ($row_PaidOrders=$rs_PaidOrders->fetch_assoc()) {
$PaidOrderId=$row_PaidOrders['order_id'];
$query_select_events = "SELECT customers.last_name AS LASTNAME,
customers.first_name AS FIRSTNAME,
order_details.member_id AS MEMBERID,
order_details.event_type AS EVENTTYPE,
order_details.event_distance AS EVENTDISTANCE,
order_details.keep_stats AS KEEPSTATS
FROM `order_details`
LEFT OUTER JOIN customers ON order_details.member_id = customers.customer_id
WHERE order_details.event_id = '$eid' AND order_details.counted_for_discount='1' AND order_details.ORDERNUM = '$PaidOrderId' ORDER BY LASTNAME ASC";
$rs_events=$conn->query($query_select_events);
if($rs_events === false){
trigger_error('SQL error:'.$query_select_events.' Error: '.$conn->error, E_USER_ERROR);
}
else{
while($row_order_details=$rs_events->fetch_assoc()){
$NAME = $row_order_details['LASTNAME'].", ".$row_order_details['FIRSTNAME'];
$member_id=$row_order_details['MEMBERID'];
$event_type=$row_order_details['EVENTTYPE'];
$event_distance=$row_order_details['EVENTDISTANCE'];
$keep_stats=$row_order_details['KEEPSTATS'];
?>
<tr>
<td><?php echo "$NAME";?></td>
etc...
My results are:
B..., H..., H..., S..., B..., R....
I am really stumped on this one. Any help would be appreciated.
The issue WAS the fact that I did not combine everything into 1 query. Once I did that, the ORDER BY last name worked properly.
SELECT apntoken,deviceid,created
FROM `distribution_mobiletokens` as dm
WHERE userid='20'
and not exists (
select 1
from `distribution_mobiletokens`
where userid = '20'
and deviceid = dm.deviceid
and created > dm.created
)
What this query does is selects all mobiletokens where the user id is equal to 20 and the deviceid is the same but chooses the newest apntoken for the device.
My database looks like below.
For more information on this query, I got this answer from another question I asked here(How to group by in SQL by largest date (Order By a Group By))
Things I've Tried
$mobiletokens = $em->createQueryBuilder()
->select('u.id,company.id as companyid,user.id as userid,u.apntoken')
->from('AppBundle:MobileTokens', 'u')
->leftJoin('u.companyId', 'company')
->leftJoin('u.userId', 'user')
->where('u.status = 1 and user.id = :userid')
->setParameter('userid',(int)$jsondata['userid'])
->groupby('u.apntoken')
->getQuery()
->getResult();
//#JA - Get the list of all the apn tokens we need to send the message to.
foreach($mobiletokens as $tokenobject){
$deviceTokens[] = $tokenobject["apntoken"];
echo $tokenobject["apntoken"]."\n";
}
die();
This gives me the incorrect response of
63416A61F2FD47CC7B579CAEACB002CB00FACC3786A8991F329BB41B1208C4BA
9B25BBCC3F3D2232934D86A7BC72967A5546B250281FB750FFE645C8EB105AF6
latestone
Any help here is appreciated!
Other Information
Data with SELECT * FROM
Data after using the SQL I provided up top.
You could use a subselect created with the querybuilder as example:
public function selectNewAppToken($userId)
{
// get an ExpressionBuilder instance, so that you
$expr = $this->_em->getExpressionBuilder();
// create a subquery in order to take all address records for a specified user id
$sub = $this->_em->createQueryBuilder()
->select('a')
->from('AppBundle:MobileTokens', 'a')
->where('a.user = dm.id')
->andWhere('a.deviceid = dm.deviceid')
->andWhere($expr->gte('a.created','dm.created'));
$qb = $this->_em->createQueryBuilder()
->select('dm')
->from('AppBundle:MobileTokens', 'dm')
->where($expr->not($expr->exists($sub->getDQL())))
->andWhere('dm.user = :user_id')
->setParameter('user_id', $userId);
return $qb->getQuery()->getResult();
}
I did this for now as a temporary fix, not sure if this is best answer though.
$em = $this->em;
$connection = $em->getConnection();
$statement = $connection->prepare("
SELECT apntoken,deviceid,created
FROM `distribution_mobiletokens` as dm
WHERE userid=:userid
and not exists (
select 1
from `distribution_mobiletokens`
where userid = :userid
and deviceid = dm.deviceid
and created > dm.created
)");
$statement->bindValue('userid', $jsondata['userid']);
$statement->execute();
$mobiletokens = $statement->fetchAll();
//#JA - Get the list of all the apn tokens we need to send the message to.
foreach($mobiletokens as $tokenobject){
$deviceTokens[] = $tokenobject["apntoken"];
echo $tokenobject["apntoken"]."\n";
}
I have a stats table that has a user_id.
I have a users table with an id that corresponds to the above user_id. I also have an employee flag in the users table.
I want to update all records in the stats table where the user_id is not that of an employee.
Ideally, I'd like to do this via the CodeIgniter Active Record, but I'm fine with a raw query as well.
Thanks!
EDIT My attempt
if($employee == false) {
$this->db->where('(default_profiles.opid = 0 OR default_profiles.opid IS NULL)');
} else {
$this->db->where('default_profiles.opid > 0');
}
$this->db->join('weekly_stats', 'default_weekly_stats.user_id = default_profiles.user_id');
$this->db->update('default_weekly_stats', $data);
However, this just yields:
UPDATE `default_weekly_stats` SET `rank` = 1 WHERE `default_weekly_stats`.`week` = '1' AND `default_weekly_stats`.`correct_picks` = '4' AND (default_profiles.opid = 0 OR default_profiles.opid IS NULL)
Haven't tried it but maybe it should be like this:
$this->db->where_not_in('users.employee_flag', '0')->join('users', 'users.user_id = stats.user_id')->update('stats', $data);
EDIT: ( based on #dianuj answer )
$this->db->set('rank', $rank );
if($employee == false) {
$this->db->where('(default_profiles.opid = 0 OR default_profiles.opid IS NULL)');
} else {
$this->db->where('default_profiles.opid > 0');
}
$this->db->update('weekly_stats ON default_weekly_stats.user_id = default_profiles.user_id');
update stats s
inner join users u on u.id = s.user_id
and u.employee = 0
set some_column = 'some_value'
unit
id fir_name sec_name
author
id name unit_id
author_paper
id author_id paper_id
I want to unify authors['same author' means the names are the same and their units' fir_names are the same], and I have to change author_paper table at the same time.
Here is what i do:
$conn->do('create index author_name on author (name)');
my $sqr = $conn->prepare("select name from author group by name having count(*) > 1");
$sqr->execute();
while(my #row = $sqr->fetchrow_array()) {
my $dup_name = $row[0];
$dup_name = formatHtml($dup_name);
my $sqr2 = $conn->prepare("select id, unit_id from author where name = '$dup_name'");
$sqr2->execute();
my %fir_name_hash = ();
while(my #row2 = $sqr2->fetchrow_array()) {
my $author_id = $row2[0];
my $unit_id = $row2[1];
my $fir_name = getFirNameInUnit($conn, $unit_id);
if (not exists $fir_name_hash{$fir_name}) {
$fir_name_hash{$fir_name} = []; #anonymous arr reference
}
$x = $fir_name_hash{$fir_name};
push #$x, $author_id;
}
while(my ($fir_name, $author_id_arr) = each(%fir_name_hash)) {
my $count = scalar #$author_id_arr;
if ($count == 1) {next;}
my $author_id = $author_id_arr->[0];
for ($i = 1; $i < $count; $i++) {
#print "$author_id_arr->[$i] => $author_id\n";
unifyAuthorAndAuthorPaperTable($conn, $author_id, $author_id_arr->[$i]); #just delete in author table, and update in author_paper table
}
}
}
select count(*) from author; #240,000
select count(distinct(name)) from author; #7,7000
It is terribly slow!!I've runned it for 5hours, it just removed about 4,0000 dup names.
How to make it run faster.I am eager for your advice
You should not prepare the second sql statement within the loop and you can make real use of the preparation when you use the ? placeholder:
$conn->do('create index author_name on author (name)');
my $sqr = $conn->prepare('select name from author group by name having count(*) > 1');
# ? is the placeholder and the database driver knows if its an integer or a string and
# quotes the input if needed.
my $sqr2 = $conn->prepare('select id, unit_id from author where name = ?');
$sqr->execute();
while(my #row = $sqr->fetchrow_array()) {
my $dup_name = $row[0];
$dup_name = formatHtml($dup_name);
# Now you can reuse the prepared handle with different input
$sqr2->execute( $dup_name );
my %fir_name_hash = ();
while(my #row2 = $sqr2->fetchrow_array()) {
my $author_id = $row2[0];
my $unit_id = $row2[1];
my $fir_name = getFirNameInUnit($conn, $unit_id);
if (not exists $fir_name_hash{$fir_name}) {
$fir_name_hash{$fir_name} = []; #anonymous arr reference
}
$x = $fir_name_hash{$fir_name};
push #$x, $author_id;
}
while(my ($fir_name, $author_id_arr) = each(%fir_name_hash)) {
my $count = scalar #$author_id_arr;
if ($count == 1) {next;}
my $author_id = $author_id_arr->[0];
for ($i = 1; $i < $count; $i++) {
#print "$author_id_arr->[$i] => $author_id\n";
unifyAuthorAndAuthorPaperTable($conn, $author_id, $author_id_arr->[$i]); #just delete in author table, and update in author_paper table
}
}
}
This should speed up things as well.
The moment I see a query and a loop I think that you have a latency problem: you query to get a set of values and then iterate over the set to do something else. That's a LOT of latency if it means a network round trip to the database for each row in the set.
It'd be better if you could do it in a single query using an UPDATE and a sub-select OR if you could batch those requests and perform all of them in one round trip.
You'll get an additional speed up if you use indexes wisely. Every column in a WHERE clause should have an index. Every foreign key should have an index.
I'd run EXPLAIN PLAN on your queries and see if there are any TABLE SCAN going on. If there is, you've got to index properly.
I wonder if a properly designed JOIN would come to your rescue?
240,000 rows in one table and 77,000 in another isn't that large a database.