PHP Unset index if no match - php

I have two tables that have these columns (I'm only showing revelant ones) :
tasks table
+----+------+
| id | todo |
+----+------+
| 1 | 0 |
| 2 | 1 |
| 3 | 1 |
| 4 | 0 |
| 5 | 1 |
+----+------+
entries table
+----+---------+---------+------+
| id | task_id | user_id | done |
+----+---------+---------+------+
| 1 | 3 | 1 | 1 |
| 2 | 5 | 2 | 1 |
| 3 | 5 | 1 | 1 |
| 4 | 2 | 1 | 0 |
+----+---------+---------+------+
I query these tables and only keep tasks where todo = 1, So I already have the data in a PHP object.
I then have two lists that the user can view : tasks that are to do, and archived (done), and tasks that are to do. I can generate the first list just fine, I'm looping through each task and entries if they have a matching task_id where user_id == $loggeduser && done == 1, and unsetting the index of those that don't match. However, I cannot find a logic to do this with my archive list, as I don't have entries to match. How do I loop my tasks and only keep those that are done, for the user? In this case, for the archive list for user 1, I'm excepting to only keep task id 3 and 5, and for user 2, only keep task id 2.
Thanks.

You can do all this using plain SQL (I suppose you're using some relational database).
This query gives you all the tasks "todo & done". To get the tasks "todo & not done", just change the "e.done = 1" to "e.done = 0". I'm sure you get the idea.
SELECT * FROM tasks t
INNER JOIN entries e ON t.id = e.task_id
AND e.user_id = [logged_user_id]
AND e.done = 1
WHERE
t.todo = 0

Related

MySQL Select to create a rank based on number of entries from a table...how to do it?

What I Have:
Table 1 : USERS (autoID, name, etc)
Table 2 : TROPHIES (autoID, name, etc)
Table 3 : VIEWS (userID, timestamp, etc)
Table 4 : CANDIDATES (userID, trophyID, etc)
What I Know:
USERS.autoID & TROPHIES.autoID
How I Do It:
I have this TROPHIES table where I store different categories users can be nomitated to.
Each User can be nominated for 1,2 or more trophies from TROPHIES table.
In the VIEWS table I store each view of the profiles for each individual user with USERS.autoID, timestamp and other data.
In the CANDIDATES table I store the TROPHIES.autoID and USERS.autoID - this way I know which User is nominated for which Trophy.
What I Need to Know
Knowing USERS.autoID & TROPHIES.autoID I want to make a TOP based on the number of entries in the last 3 days for example in VIEWS table of all USERS that are listed in CANDIDATES table for that specific trophy and find out the POSITION on that top of a specific user.
So let's say the user with the autoID 1 is nominated to the TROPHY with the autoID 10 and has 100 entries in the VIEWS table on the last 3 days but there are other 3 users nominated to the TROPHY with the autoID 10 who have more than 100 entries in the last 3 days so...I need a select that would return the number 4.
My Questions:
Can I do that with 1 single SELECT query? If yes...how? If no...how could I make this query to spend as little resources as possible.
Thanks!
[EDIT]
Here is some data
TABLE 1 - USERS
+--------+-------+
| autoID | name |
+--------+-------+
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
+--------+-------+
TABLE 2 - TROPHIES
+--------+------------+
| autoID | name |
+--------+------------+
| 1 | Baseball |
| 2 | Basketball |
| 3 | Boxing |
+--------+------------+
TABLE 3 - VIEWS
+--------+--------+------------+
| autoID | userID | timestamp |
+--------+--------+------------+
| 1 | 2 | 1551632970 |
| 2 | 2 | 1551632971 |
| 3 | 3 | 1551632972 |
| 4 | 1 | 1551632973 |
| 5 | 2 | 1551632974 |
| 6 | 1 | 1551632975 |
| 7 | 3 | 1551632976 |
| 8 | 1 | 1551632977 |
| 9 | 2 | 1551632978 |
| 10 | 3 | 1551632979 |
| 11 | 3 | 1551632980 |
| 12 | 3 | 1551632981 |
+--------+--------+------------+
TABLE 4 - CANDIDATES
+--------+--------+----------+
| autoID | userID | trophyID |
+--------+--------+----------+
| 1 | 2 | 1 |
| 2 | 3 | 3 |
| 3 | 1 | 2 |
| 4 | 1 | 1 |
+--------+--------+----------+
In the end I want to be able to know on which position a User is for a specific trophy based on the entries from the VIEWS table.
Let's say I want to check the position of the USER with the autoID = 1 for Baseball (trophy which has autoID = 1) after timestamp 1551632972.
So...First we have to see which users are listed in this trophy so we can ignore the entries from the table VIEWS for the other users. Trophy with the autoID 1 (Baseball) has only two users listed - user1 and user2.
Now I want to see how many entries both have so I can be able to find out which is the position of the user1 on this top.
So if we select and count all the entries from the table VIEWS for user1 where timestamp is equal or bigger than 1551632972 we will get number 3 and if we do the same thing for the user2 we will get 2 and since 3 is bigger than 2, user1 will be on 1st place and user2 will be on the 2nd place.
I am searching for a way to get the place in the TOP for a specific user inside a specific sport using a single MySQL query (if possible) or finding the best solution to do so...
I found the solution...I will just leave it here in case someone else will need it.
SELECT
U.autoId,
U.name,
U1.position
FROM USERS U
JOIN (SELECT
#rownum := #rownum + 1 AS position,
U.autoId,
U.name,
COUNT(V.autoID) as "Nr"
FROM USERS U
JOIN VIEWS V ON V.userID= U.autoID
JOIN CANDIDATESC ON C.userID= U.autoID
JOIN (SELECT #rownum := 0) R
WHERE C.trophyID= 'id_of_trophy_wanted' GROUP BY U.autoID ORDER BY Nr DESC) as U1 ON U1.autoID =
U.autoID
WHERE U.autoID = 'id_of_user_wanted'
Thanks to the ones who tried to help!

Reorder mysql table ROWS on front end, and update backend [duplicate]

I have a table of food items. They have a "Position" field that represents the order they should appear in on a list (listID is the list they are on, we don't want to re-order items on another list).
+--id--+--listID--+---name---+--position--+
| 1 | 1 | cheese | 0 |
| 2 | 1 | chips | 1 |
| 3 | 1 | bacon | 2 |
| 4 | 1 | apples | 3 |
| 5 | 1 | pears | 4 |
| 6 | 1 | pie | 5 |
| 7 | 2 | carrots | 0 |
| 8,9+ | 3,4+ | ... | ... |
+------+----------+----------+------------+
I want to be able to say "Move Pears to before Chips" which involves setting the position of Pears to position 1, and then incrementing all the positions inbetween by 1. so that my resulting Table look like this...
+--id--+--listID--+---name---+--position--+
| 1 | 1 | cheese | 0 |
| 2 | 1 | chips | 2 |
| 3 | 1 | bacon | 3 |
| 4 | 1 | apples | 4 |
| 5 | 1 | pears | 1 |
| 6 | 1 | pie | 5 |
| 7 | 2 | carrots | 0 |
| 8,9+ | 3,4+ | ... | ... |
+------+----------+----------+------------+
So that all I need to do is SELECT name FROM mytable WHERE listID = 1 ORDER BY position and I'll get all my food in the right order.
Is it possible to do this with a single query? Keep in mind that a record might be moving up or down in the list, and that the table contains records for multiple lists, so we need to isolate the listID.
My knowledge of SQL is pretty limited so right now the only way I know of to do this is to SELECT id, position FROM mytable WHERE listID = 1 AND position BETWEEN 1 AND 5 then I can use Javascript (node.js) to change position 5 to 1, and increment all others +1. Then UPDATE all the records I just changed.
It's just that anytime I try to read up on SQL stuff everyone keeps saying to avoid multiple queries and avoid doing syncronous coding and stuff like that.
Thanks
This calls for a complex query that updates many records. But a small change to your data can change things so that it can be achieved with a simple query that modifies just one record.
UPDATE my_table set position = position*10;
In the old days, the BASIC programming language on many systems had line numbers, it encouraged spagetti code. Instead of functions many people wrote GOTO line_number. Real trouble arose if you numbered the lines sequentially and had to add or delete a few lines. How did people get around it? By increment lines by 10! That's what we are doing here.
So you want pears to be the second item?
UPDATE my_table set position = 15 WHERE listId=1 AND name = 'Pears'
Worried that eventually gaps between the items will disappear after multiple reordering? No fear just do
UPDATE my_table set position = position*10;
From time to time.
I do not think this can be conveniently done in less than two queries, which is OK, there should be as few queries as possible, but not at any cost. The two queries would be like (based on what you write yourself)
UPDATE mytable SET position = 1 WHERE listID = 1 AND name = 'pears';
UPDATE mytable SET position = position + 1 WHERE listID = 1 AND position BETWEEN 2 AND 4;
I've mostly figured out my problem. So I've decided to put an answer here incase anyone finds it helpful.
I can make use of a CASE statement in SQL. Also by using Javascript beforehand to build my SQL query I can change multiple records.
This builds my SQL query:
var sql;
var incrementDirection = (startPos > endPos)? 1 : -1;
sql = "UPDATE mytable SET position = CASE WHEN position = "+startPos+" THEN "+endPos;
for(var i=endPos; i!=startPos; i+=incrementDirection){
sql += " WHEN position = "+i+" THEN "+(i+incrementDirection);
}
sql += " ELSE position END WHERE listID = "+listID;
If I want to move Pears to before Chips. I can set:
startPos = 4;
endPos = 1;
listID = 1;
My code will produce an SQL statement that looks like:
UPDATE mytable
SET position = CASE
WHEN position = 4 THEN 1
WHEN position = 1 THEN 2
WHEN position = 2 THEN 3
WHEN position = 3 THEN 4
ELSE position
END
WHERE listID = 1
I run that code and my final table will look like:
+--id--+--listID--+---name---+--position--+
| 1 | 1 | cheese | 0 |
| 2 | 1 | chips | 2 |
| 3 | 1 | bacon | 3 |
| 4 | 1 | apples | 4 |
| 5 | 1 | pears | 1 |
| 6 | 1 | pie | 5 |
| 7 | 2 | carrots | 0 |
| 8,9+ | 3,4+ | ... | ... |
+------+----------+----------+------------+
After that, all I have to do is run SELECT name FROM mytable WHERE listID = 1 ORDER BY position and the output will be as follows::
cheese
pears
chips
bacon
apples
pie

how to merge multiple rows with same id mysql

I'm new posting here but the community have been my best resource on my projects so far.
I'm a dumb/dummy Mysql "wanna be" and I'm in the middle of a project that is making me go mad.
I have a table from wordpress plugin buddypress that pairs meta_key and meta_values in order to create something akin to a taxonomy. My duty is to use these paired values to implement an advanced group search. Here is the original table:
--------------------------------------------
id | group_id | meta_key | meta_value
--------------------------------------------
1 | 1 | time-zone | Kwajalein
2 | 1 | playstyle | hardcore
3 | 1 | recruiting-status | Open
4 | 1 | ilvl | 115
5 | 1 | main-raid | Final Coil of Bahamut
6 | 1 | voicechat | fc.teamspeak3.com
etc....
Using a view I managed to create a more friendly searchable table for begginers :
gid| time-zone| playstyle | main-raid
--------------------------------------------
1 | | |
1 |Kwajalein | |
1 | | hardcore |
1 | | |
1 | | | Final Coil of Bahamut
1 | | |
And here is the view code:
SELECT distinct
group_id AS 'gid',
IF(meta_key='recruiting-status',meta_value,'') AS 'Recruitment',
IF(meta_key='server',meta_value,'') AS 'server',
IF(meta_key='time-zone',meta_value,'') AS 'tzone',
IF(meta_key='main-raid',meta_value,'') AS 'raid',
IF(meta_key='raid-days',meta_value,'') AS 'days',
IF(meta_key='playstyle',meta_value,'') AS 'playstyle',
IF(meta_key='raid-progression',meta_value,'') AS 'progression',
IF(meta_key='raid-time',meta_value,'') AS 'time',
IF(meta_key='tanker-spot',meta_value,'') AS 'tank',
IF(meta_key='healer-spot',meta_value,'') AS 'healer',
IF(meta_key='melee-dps-spot',meta_value,'') AS 'melee',
IF(meta_key='ranged-dps-spot',meta_value,'') AS 'ranged',
IF(meta_key='magic-dps-spot',meta_value,'') AS 'magic',
IF(meta_key='ilvl',meta_value,'') AS 'ilvl',
IF(meta_key='voicechat',meta_value,'') AS 'voice',
IF(meta_key='voicechatpass',meta_value,'') AS 'voicep',
FROM wpstatic_bp_groups_groupmeta
The point is, I need to merge that result (view) so all the group_id=1 or 2 or 3, etc stand in one single row, like this:
gid| time-zone| playstyle | main-raid
--------------------------------------------
1 |Kwajalein | hardcore | Final Coil of Bahamut
2 |SaoPaulo | regular | Second Coil of Bahamut
etc
Can anyone help me there?
Just surround your IFs in a MAX, or another aggregate function that will capture the non-empty strings (e.g., GROUP_CONCAT), and add a GROUP BY group_id add the end. For example,
SELECT
group_id AS gid,
MAX(IF(meta_key='recruiting-status',meta_value,'')) AS 'Recruitment',
MAX(IF(meta_key='server',meta_value,'')) AS 'server',
...
FROM wpstatic_bp_groups_groupmeta
GROUP BY group_id

Selecting multiple tables MySQL and retrieving different data

I have 4 tables that I need to pull data from. I need to count how many people are signed for a single event and see if a user is applied for an event.
These are my table setups:
TABLE: users
+----+----------+-------+--------+-------+
| id | username | level | class | guild |
+----+----------+-------+--------+-------+
| 1 | example1 | 100 | Hunter | blah |
| 2 | example2 | 105 | Mage | blah2 |
| 3 | example3 | 102 | Healer | blah |
+----+----------+-------+--------+-------+
ID is primary
TABLE: event_randoms
+----+----------+-------+--------+----------+----------+
| id | username | level | class | apped_by | event_id |
+----+----------+-------+--------+----------+----------+
| 1 | random1 | 153 | Hunter | 3 | 3 |
| 2 | random2 | 158 | Healer | 3 | 1 |
| 3 | random3 | 167 | Warrior| 1 | 3 |
+----+----------+-------+--------+----------+----------+
ID is primary
apped_by should be foreign key to users.id
event_id should be foreign key to events.id
TABLE: events
+----+------------+------------+-----------+-----------+-----------+
| id | event_name | event_date | initiator | min_level | max_level |
+----+------------+------------+-----------+-----------+-----------+
| 1 | event1 | date1 | 1 | 100 | 120 |
| 2 | event2 | date2 | 1 | 121 | 135 |
| 3 | event3 | date3 | 1 | 100 | 120 |
| 4 | event4 | date4 | 1 | 150 | 200 |
+----+------------+------------+-----------+-----------+-----------+
ID is primary
TABLE: event_apps
+----+----------+--------------+
| id | event_id | applicant_id |
+----+----------+--------------+
| 1 | 3 | 2 |
| 2 | 4 | 2 |
| 3 | 3 | 1 |
| 4 | 1 | 3 |
+----+----------+--------------+
ID is primary
event_id should be foreign key to events.id
applicant_id should be foreign key to users.id
I will be the first to admit that I am very new to this. I just learned how to use MySQL a few days ago. I can grab stuff from a single table, but I am unsure how to grab from multiple tables.
This is the SQL query I tried
SELECT DD_events.id, event_id, applicant_id, guild, level, class, DD_users.id
FROM DD_events, DD_event_apps, DD_users
WHERE DD_event_apps.event_id = DD_events.id
AND DD_event_apps.applicant_id = DD_users.id
and tried to print_r an array but the array turns up empty.
So a few questions pertain to this:
1: How would I count and display as a number how many people (users and randoms) are signed up for an event?
eg: event 3 should have 4 total (2 users and 2 randoms)
2: How do I see if a particular individual is signed for an event and display text based if they are or not?
eg: user 1 is signed up for event 3 so it would be "Registered" but user 2, who is not signed, would display "Not Registered"
3: I want to display info for who is signed for a particular event in 2 tables, 1 for users and another for randoms.
eg: Event 3 would have 2 users info (username, guild, class, level) under the users table and then 2 random users info (name, class, level, what user applied this person) in the random table.
Any and all help is appreciated even if you can answer 1 part.
I'm thinking this would be your base query:
SELECT
event.id,
app.applicant_id,
usr.guild,
usr.level,
usr.class,
usr.id AS Userid
FROM
DD_events event
JOIN
DD_event_apps app
ON (event.id = app.event_id)
LEFT JOIN
DD_users usr
ON (app.user_id = usr.id)
You can make modifications to this to aggregate it, like so:
SELECT
event.id,
COUNT(app.applicant_id) AS ApplicantCount,
COUNT(DISTINCT usr.guild) AS UniqueGuilds,
COUNT(DISTINCT usr.level) AS UniqueLevels,
COUNT(DISTINCT usr.class) AS UniqueClasses,
COUNT(DISTINCT usr.id) AS UniqueUsers
FROM
DD_events event
JOIN
DD_event_apps app
ON (event.id = app.event_id)
LEFT JOIN
DD_users usr
ON (app.user_id = usr.id)
GROUP BY
event.id
I could write those scripts for you, but I think this provides a good starting point for you to continue from. You'll find that T-SQL is fairly simple when you are trying to get the results you are looking for. Hope this helps!
<?php $query = "SELECT count(*) AS numbuh FROM DD_event_apps WHERE event_id = {$row['id']}";
try
{
// These two statements run the query against your database table.
$stmt = $db->prepare($query);
$stmt->execute();
}
catch(PDOException $ex)
{
// Note: On a production website, you should not output $ex->getMessage().
// It may provide an attacker with helpful information about your code.
die("Failed to run query: " . $ex->getMessage());
}
echo($query);
// Finally, we can retrieve all of the found rows into an array using fetchAll
$count = $stmt->fetchAll();
echo($count['numbuh']); ?>

How do I compare 2 tables looking for missing items

I have two tables one that contains a huge list of items and another that trading for those items.
Here are examples tables:
The main table
| ID | TITLE | STATUS | TRADE |
-------------------------------
| 1 | test1 | 1 | 1 |
| 2 | test2 | 1 | 1 |
| 3 | test3 | 1 | 0 |
| 4 | test4 | 0 | 1 |
The trade table
| ID | TRADER | ITEM | URL |
------------------------------------------------------
| 1 | 2 | 1 | HTTP://www.test.com/itemOne |
| 2 | 5 | 3 | HTTP://www.test.com/itemThree |
| 3 | 5 | 4 | HTTP://www.test.com/itemFour |
Say I want to have a list of all the items that are not being traded by trader 5 and have a status of 1. So when trader 5 comes to the site they will be able to select the remaining items to trade.
Here is what I have tried:
$sql = "SELECT m.id, m.title
FROM main AS m, trade AS t
WHERE m.trade >= 1 && m.status = 1 &&
t.trader <>". mysql_real_escape_string($traderID);
This code just doesn't work. Any ideas on this?
It is not clear to me what column in Trades is an FK to Main. Below, I have assumed it is the Item column:
select m.id, m.title
from Main m
where not exists (
select *
from trade
where m.id = item
and trader = 5
)
and m.status = 1
Try this:
SELECT id, title FROM main
WHERE status = 1 AND id NOT IN
(SELECT item FROM trade WHERE trader = 5);
This will grab a list of every title in main with a status of 1, but limit the items based on a subquery which gets a list of ids already traded by trader 5 (i.e. items "not in" the list of items returned as having been traded by trader 5).
I'll leave it to you to update the query to be parameterized as needed.
Note that I'm assuming that item in trade is a foreign key to the id field in main, since you didn't specify it.

Categories