Gathering information in 1 row using related tables - php

I am trying to build my database using related tables. I am getting the right output from the database, however - Since the user is the same, and the only change in data is the courses, I would like to gather the values "Engelsk" and "Matematik" in the same row, instead of having two outputs which are virtually the same, except the courses.
Is this even possible without having this in the same row in the database? And if so, I'd very much like to know how :)
Array
(
[0] => Array
(
[Type] => Elev
[Username] => test
[Name] => Test Testsen
[Grade] => 9. Klasse
[Course] => Engelsk
)
[1] => Array
(
[Type] => Elev
[Username] => test
[Name] => Test Testsen
[Grade] => 9. Klasse
[Course] => Matematik
)
)
So basically what I would like to achieve is something like this:
Array
(
[0] => Array
(
[Type] => Elev
[Username] => test
[Name] => Test Testsen
[Grade] => 9. Klasse
[Course] => Engelsk, Matematik
)
My query looks like this:
SELECT
*
FROM
lek_Essentials
LEFT JOIN
lek_Type
ON
lek_Essentials.TypeId = lek_Type.TypeId
LEFT JOIN
lek_Grades
ON
lek_Essentials.GradeId = lek_Grades.GradeId
LEFT JOIN
lek_GradeCourses
ON
lek_Grades.GradeId = lek_GradeCourses.GradeId
LEFT JOIN
lek_Courses
ON
lek_GradeCourses.CourseId = lek_Courses.CourseId
LEFT JOIN
lek_Request
ON
lek_Courses.CourseId = lek_Request.CourseId
WHERE
lek_Essentials.UserId = lek_Request.UserId

It's not exactly clear what tables each of the columns in your array are coming from but in MySQL you can use GROUP_CONCAT to aggregate the two rows into one:
SELECT t.type,
e.username,
e.name,
g.grade,
group_concat(c.course) course
FROM lek_Essentials e
LEFT JOIN lek_Type t
ON e.TypeId = t.TypeId
LEFT JOIN lek_Grades g
ON e.GradeId = g.GradeId
LEFT JOIN lek_GradeCourses gc
ON g.GradeId = gc.GradeId
LEFT JOIN lek_Courses c
ON gc.CourseId = c.CourseId
LEFT JOIN lek_Request r
ON c.CourseId = r.CourseId
WHERE e.UserId = r.UserId
group by t.type, e.username, e.name, g.grade

Related

Connecting tables when querying in MySQL

I have 3 tables: tco_articles, tco_module_eostext and tco_articles_modules. My tco_articles has unique id key. One for each article. My tco_module_eostext has unique instance_id that belongs to each article.
My tco_articles_modules contains all article_ids, but have 9 times as much instance_ids that are used in other tables.
So I can have article_id with instance_id that when you query in the tco_module_eostext will return empty.
I'd like to make a query that will return correct body text for the correct article.
So far I have:
global $wpdb;
$posts = array();
$ids = $wpdb->get_results('SELECT DISTINCT instance_id, article_id FROM tco_articles_modules', ARRAY_A);
This returns array with all the instances and ids like:
Array
(
[0] => Array
(
[instance_id] => 928615
[article_id] => 129396
)
[1] => Array
(
[instance_id] => 928616
[article_id] => 129396
)
[2] => Array
(
[instance_id] => 928617
[article_id] => 129396
)
[3] => Array
(
[instance_id] => 928618
[article_id] => 129396
)
You can see that the article_ids are the same but instance_id. When you put
$wpdb->get_results('SELECT body FROM tco_module_eostext WHERE instance_id=928617 ', ARRAY_A);
You may get empty, but for
$wpdb->get_results('SELECT body FROM tco_module_eostext WHERE instance_id=928618 ', ARRAY_A);
You could have some body text.
This is my problem. I need to go through all of them and filter out the not empty ones and assign them correct article. I managed to output the articles
foreach ($ids as $key => $value) {
$instance_ID = $value['instance_id'];
$article_ID = $value['article_id'];
$article_out = $wpdb->get_results('SELECT * FROM tco_articles WHERE id='.$article_ID.' ', ARRAY_A);
$posts[$article_ID] = $article_out[0];
}
Which returns something like:
Array
(
[129396] => Array
(
[id] => 129396
[headline] => Bla bla bla title
[intro] => This is cool article intro
[needs_review] => 0
[published] => 2014-12-16 09:17:00
[unpublished] =>
[hidden] => 0
[no_single_page] => 0
[permalink] => link-perma-link-here
[internal_slug] =>
[type_id] => 3
[thread_id] => 0
[news_id] => 0
[header_game_id] => 0
[puff_hh_id] => 0
[puff_title] =>
[hdrcol_id] => 900
[review_queued] =>
[lock_timeout] => 0
[created] => 2014-12-16 09:17:00
[updated] => 2015-01-16 13:51:30
[created_by] => 84142
[updated_by] => 84142
)
...
Now I'd like to append the body text from the tco_module_eostext table.
Is there a query I can use to do this automatically or to do this one at the time and then append to the $posts array?
The foreach method of querying is kinda slow when you have 180000+ posts.
Any help is appreciated.
If you are sure that there is always only one row in tco_module_eostext against each article_id, you can use JOIN (inner join), which will only show one row for each article_id.
SELECT a.*, t.body
FROM tco_articles a
JOIN tco_articles_modules m ON m.article_id = a.id
JOIN tco_module_eostext t ON m.instance_id = t.instance_id
//WHERE .....
But, this will not show any row of some articles if there is no entry in other two tables for that article_id. But there is still way to solve this. We can use LEFT OUTER JOIN and then make sure we only make the join if there is any row in tco_module_eostext for any instace_id. This will make sure you get at least the article info from tco_articles table when there is no data in other tables.
SELECT a.*, t.body
FROM tco_articles a
LEFT OUTER JOIN tco_articles_modules m ON m.article_id = a.id AND EXISTS ( SELECT NULL FROM tco_module_eostext WHERE instance_id = m.instance_id )
LEFT OUTER JOIN tco_module_eostext t ON m.instance_id = t.instance_id
//WHERE .....
Why not use a query with join?
Not tested!:
SELECT
article.*,
text.body as bodytext
FROM
tco_articles_modules AS modules LEFT OUTER JOIN
tco_module_eostext AS text ON
modules.instance_id = text.instance_id LEFT OUTER JOIN
tco_articles AS article ON
article.id = modules.article_id
it should get all articles with the assigned article_id from tco_articles_modules
Have a look at OUTER Join - you may want to replace this with an INNER JOIN for faster Queries. Also you ma want an WHERE condition for filtering in the query. Watch also out for the right indexing in mysql table - each joining column should be indexed - this will get much more faster results.

Filtering a MySQL query with multiple conditions

I have my output array named "Feed Items" (fi):
(
[0] => Array
(
[reg] => 2015-08-03 13:39:00
[id] => fd7ec4107d16b07c1a13cbdd386af8d2cb05ffca
[user_id] => de5fd44db1760b006b1909cf1db11a78b38e455c
[img] => edee88e88cf6e17732e393b5433cfd894662902e
[type] => new_join_ambition
)
)
I generate an array named "RemovedFeedItems" (rfi) that has the following structure:
(
[0] => Array
(
[object_id] => fd7ec4107d16b07c1a13cbdd386af8d2cb05ffca
[postee_id] => de5fd44db1760b006b1909cf1db11a78b38e455c
[type] => new_join_ambition
)
)
My mission is to not get the records that have the following condition:
ri.id == rfi.object_id && ri.user_id == rfi.postee_id && ri.type == rfi.type
The query that I use to get the Feed Items array is:
SELECT
i.registered AS reg,
a.id,
u.id AS user_id,
ui.image_id AS img,
'new_join_ambition' AS type,
FROM x_ambition_invites i
LEFT JOIN x_user u
ON i.to = u.id
LEFT JOIN x_user_images ui
ON u.id = ui.user_id
LEFT JOIN x_ambitions a
ON i.ambition_id = a.id
WHERE a.registered
BETWEEN '2014-07-21 14:25:03' AND '2015-08-05 12:04:41'
AND i.to != '8fa7a1679560876eaf2f8060abd916b692c719dc'
AND i.to IN ('de5fd44db1760b006b1909cf1db11a78b38e455c')
How can I adapt my query to implement the condition to remove the stated record from the FeedItems Array?
Thanks in advance.
Try with an inline table:
SELECT ... FROM ... WHERE (a,b,c) NOT IN (SELECT a1, b1, c1 UNION SELECT a2, b2, c2 UNION SELECT...)
The drawback is that you'll have to build a large query string. :-(

Using LEFT OUTER JOIN to build query results

There are three tables like this:
store_stock:
ID ItemWeaveType ItemModel Cost Price
7 3 4 10.00 15.00
store_item_weaves:
ID WeaveID
3 MC
store_item_models:
ID ModelID
4 HV
I am trying to do a query to gather all of the data for item with the stock ID of 7. As a finished result, I would like an array like:
Array ( [ID] => 7 [ItemWeaveType] => MC [ItemModel] => HV [Cost] => 10.00 [Price] => 15.00)
So, I need to join the data from the tables store_item_weaves and store_item_models.
Here is what I have so far:
$query = $db->query("SELECT * FROM `store_stock` s
left outer join `store_item_weaves` w on w.`ID`=s.`ItemWeaveType`
left outer join `store_item_models` m on m.`ID`=s.`ItemModel`
where s.`ID`=7");
This returns an array like:
Array ( [ID] => 7 [ItemWeaveType] => 3 [ItemModel] => 4 [Cost] => 10.00 [Price] => 15.00 [WeaveID] => MC [ModelID] => HV )
So, I'm almost there. Instead of using the values of WeaveID and ModelID for ItemWeaveType and ItemModel, it is adding it onto the array.
Any ideas?
Use a columns list instead of just * to make sure you get the values you want:
$query = $db->query("SELECT s.ID, w.WeaveId, m.ModelId, s.Cost, s.Price FROM `store_stock` s
left outer join `store_item_weaves` w on w.`ID`=s.`ItemWeaveType`
left outer join `store_item_models` m on m.`ID`=s.`ItemModel`
where s.`ID`=7");

Mysql inner join returning repeated results

Im trying to pull a character from a mysql database. The character table has 6 columns that link to a foreign item id from the item table, i need to link each item to get the item id, name, and foreign image id, then i need to link that foregin image id to my image table. and pull the image url. The code i coded below to do this is giving me duplicate image urls. Does anyone know whats wrong with it?
This is my results. The image urls are repeating themselfs. I took project_users out to test it and the same thing happened its not being used now but will be used in the future.
I made a sqlfiddle but it looks like its working correct here http://sqlfiddle.com/#!2/7896e/8
Array ( [name] => test1241 [0] => test1241 [gender] => [1] => [left_arm] => Images/Items/leftArm.png [2] =>
Images/Items/leftArm.png [legs] => Images/Items/legs.png [3] => Images/Items/legs.png [torso] =>
Images/Items/torso.png [4] => Images/Items/torso.png [head] => Images/Items/head.png [5] => Images/Items/head.png [hair] => Images/Items/hair.png [6] => Images/Items/hair.png [right_arm] => Images/Items/rightArm.png [7] => Images/Items/rightArm.png )
$sql = "SELECT
pc.project_characters_name as name,
pc.project_characters_gender as gender,
pia1.project_images_url as left_arm,
pia2.project_images_url as legs,
pia3.project_images_url as torso,
pia4.project_images_url as head,
pia5.project_images_url as hair,
pia6.project_images_url as right_arm
FROM project_characters AS pc
INNER JOIN project_users AS pu ON pc.fk_project_users_id = pu.project_users_id
INNER JOIN project_items AS pi1 ON pc.project_characters_left_arm = pi1.project_items_id
INNER JOIN project_items AS pi2 ON pc.project_characters_legs = pi2.project_items_id
INNER JOIN project_items AS pi3 ON pc.project_characters_torso = pi3.project_items_id
INNER JOIN project_items AS pi4 ON pc.project_characters_head = pi4.project_items_id
INNER JOIN project_items AS pi5 ON pc.project_characters_hair = pi5.project_items_id
INNER JOIN project_items AS pi6 ON pc.project_characters_right_arm = pi6.project_items_id
INNER JOIN project_images AS pia1 ON pi1.fk_project_images_id = pia1.project_images_id
INNER JOIN project_images AS pia2 ON pi2.fk_project_images_id = pia2.project_images_id
INNER JOIN project_images AS pia3 ON pi3.fk_project_images_id = pia3.project_images_id
INNER JOIN project_images AS pia4 ON pi4.fk_project_images_id = pia4.project_images_id
INNER JOIN project_images AS pia5 ON pi5.fk_project_images_id = pia5.project_images_id
INNER JOIN project_images AS pia6 ON pi6.fk_project_images_id = pia6.project_images_id
WHERE pc.project_characters_name=:name LIMIT 1";
You can try using the keyword DISTINCT
to select only distinct result.
Example :
SELECT DISTINCT yourField FROM tables;

SQL left join part of the array is empty

My problem is the following code the comment&rating area of the array should have a comment in it as the DB history table does ...?
SELECT users.uid, users.username, history.user_id, history.comment, history.rating
FROM history
LEFT JOIN users
ON users.uid=history.user_id
WHERE history.book_id="$bid"
It returns :
Array ( [uid] => 3 [username] => Reign [user_id] => 3 [comment] => [rating] => )
Then you want to use an INNER JOIN. A LEFT JOIN will return NULL values.
SELECT users.uid, users.username, history.user_id, history.comment, history.rating
FROM history
INNER JOIN users
ON users.uid=history.user_id
WHERE history.book_id="$bid"

Categories