access violation Joining a table on another table twice using Laravel - php

So I got a table called matches containing 2 teams ID, and these teams are in the same table called clans
matches
team1_id | team2_id
2 | 4
1 | 2
4 | 1
and
Clans
ID | Name
2 | abc
1 | cde
4 | efg
My goal is that when I print this out at the webpage, it shows the teams names instead of their IDs. Now to explain it simple, I'm using laravel, with the following code:
$unfinished = DB::table('matches')->where('team1_score', NULL)
->join('matches', 'matches.team1_id', '=', 'clans.id')
->join('matches', 'matches.team2_id', '=', 'clans.id')
->select('clans.clan_name as team1_name', 'clan_name as team2_name', 'matches.id'
)->get();
and I need it all stored in $unfinished. Naturally, this code does'nt work, and I think I understand why. What i just can't figure out however, is how to solve this so that it will work. It spits out the following exakt error:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'matches' (SQL: select clans.clan_name as team1_name, clan_name as team2_name, matches.id, tournaments.name from matches inner join tournaments on tournaments.id = matches.tournaments_id inner join matches on matches.team1_id = clans.id inner join matches on matches.team2_id = clans.id where team1_score is null)

Use aliases:
$unfinished = DB::table('matches')->where('team1_score', NULL)
->join('clans AS clans1', 'matches.team1_id', '=', 'clans1.id')
->join('clans AS clans2', 'matches.team2_id', '=', 'clans2.id')
->select('clans1.clan_name as team1_name', 'clans2.clan_name as team2_name', 'matches.id'
)->get();

Related

How can I filter one column by two AND conditions?

The question has been resolved. But if you have a "better" or another way to do it then feel free to add a comment! Thanks all for reading! :)
I'm trying to make a dynamic query. Everything is working perfectly except for one thing. I've Google'd for days but I can't figure out how I can make the following work;
SELECT project.name, project.description, track.name, track.description
, SDG.position, SDG.title, SDG.description
, sprint_numbers.number, sprint_options.option
, resources.name, resources.description
, URLs.URL
FROM project INNER JOIN track ON project.track_id = track.id
INNER JOIN project_SDG ON project.id = project_SDG.project_id
INNER JOIN SDG ON project_SDG.SDG_id = SDG.id
INNER JOIN sprint ON sprint.project_id = project.id
INNER JOIN sprint_numbers ON sprint_numbers.id = sprint.sprint_number_id
INNER JOIN sprint_options ON sprint_options.id = sprint.sprint_option_id
INNER JOIN resources ON project.id = resources.project_id
INNER JOIN URLs ON URLs.id = resources.id
WHERE 1=1
AND MATCH (project.name) AGAINST (:name_project)
AND MATCH (project.description) AGAINST (:description_project)
AND SDG.id = :SDG_1
AND SDG.id = :SDG_2
The query executes but does not return anything. The problem is that the SDG.id can't be true to both :SDG_1 and :SDG_2.
Using the OR operator works, but that does not return it the way I want. It must "act" as an AND operator. (:SDG_1 & :SDG_2 are the names of the PHP variables that bind to the SQL statement parameters.)
The query should filter for both values. The values given to :SDG_1 and :SDG_2 must both exist in the SDG.id column of the project_SDG table. If the value of :SDG_1 exists, but :SDG_2 not, then the query should not return anything.
I found this on StackOverflow but it did not work for me: SELECTING with multiple WHERE conditions on same column
I hope someone can help me out.
EDIT: minimal reproducible example
QUERY:
SELECT * FROM project
INNER JOIN project_SDG ON project.id = project_SDG.project_id
INNER JOIN SDG ON project_SDG.SDG_id = SDG.id
WHERE SDG.id = 1 AND SDG.id = 7 AND SDG.id = 14 AND SDG.id = 17
Project table
+------------------+---------------------------+------------+
| id name | description | track_id |
+------------------+---------------------------+------------+
| 1 project name | This is a description 2 | |
+------------------+---------------------------+------------+
SDG table
+-----+-----------+-------------+---------------------------------------------+
| id | position | title | description |
+-----+-----------+-------------+---------------------------------------------+
| 1 | 1 | SDG 1 to 17 | There're multiple SDGs ranging from 1 to 17 |
| 17 | 17 | SDG 1 to 17 | There're multiple SDGs ranging from 1 to 17 |
+-----+-----------+-------------+---------------------------------------------+
project.SDG (bridge-table)
+------------+--------+
| project.id | SDG.id |
+------------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
+------------+--------+
You want for each project.id both values :SDG_1 and :SDG_2 to exist for SDG.id, so use this in the WHERE clause:
WHERE 1=1
AND MATCH (project.name) AGAINST (:name_project)
AND MATCH (project.description) AGAINST (:description_project)
AND project.id IN (
SELECT project_id
FROM project_SDG
WHERE SDG_id IN (:SDG_1, :SDG_2)
GROUP BY project_id
HAVING COUNT(DISTINCT SDG_id) = 2
)
Could you provide a minimal reproducible example for your query?
Generally speaking, one field cannot be equal to two different values in the same time. So, you have either mixed up the logical operators or you need two different fields.
I can assume that in your case there may be several related records with different values. In this case, you need to join the same table twice with different aliases. Let's say as SDG1 and SDG2. After that you can compare
... `SDG1`.id = :SDG_1 AND `SDG2`.id = :SDG_2
Update:
The win trick is groupping. You can enumerate all required SDG IDs and count how many of them is in group. Just for example in case of two IDs:
SELECT project.id
FROM project
JOIN project_SDG ON project_SDG.project_id = project.id
JOIN SDG ON SDG.id = project_SDG.SDG_id
WHERE SDG.id IN(1,2)
GROUP BY project.id
HAVING COUNT(*) = 2
See my sandbox here: https://www.db-fiddle.com/f/pixe3Zcs75Mq2PyCYPk913/0
If you need all project's fields, you have to put this into sub-query as
... WHERE id IN ( subquery here )
Subquery example: https://www.db-fiddle.com/f/pixe3Zcs75Mq2PyCYPk913/1
I have already answered here, but I have another approch.
1. Find bunch of IDs assotiated with some project
To find project IDs we can test lonely pivot table without any join:
SELECT project_id FROM project_SDG
WHERE SDG_id IN(1,2,6)
GROUP BY project_id HAVING COUNT(*) = 3
it gives us list of Project IDs
2. Access all project fields and add extra conditions
SELECT project.*
FROM project
JOIN (
SELECT project_id FROM project_SDG
WHERE SDG_id IN(1,2,6)
GROUP BY project_id HAVING COUNT(*) = 3
) AS ids ON ids.project_id = project.id
WHERE
MATCH(project.name) AGAINST ('project') AND
MATCH(project.description) AGAINST ('sit')
you can play with it here: https://www.db-fiddle.com/f/pixe3Zcs75Mq2PyCYPk913/3
3. Prepare query on the PHP side
I will use known technique to prepare SQL statement.
$ids = [1, 2, 6]; // it can come from request parameters
$text1 = 'project';
$text2 = 'sit';
// build ?,?,?,... pattern
$qmarks = implode(',', array_fill(0, count($ids), '?'));
// Use SQL query above
$sth = $dbh->prepare("
SELECT project.*
FROM project
JOIN (
SELECT project_id FROM project_SDG
WHERE SDG_id IN({$qmarks})
GROUP BY project_id HAVING COUNT(*) = ?
) AS ids ON ids.project_id = project.id
WHERE
MATCH(project.name) AGAINST (?) AND
MATCH(project.description) AGAINST (?)
");
$sth->execute(array_merge($ids, [count($ids), $text1, $text2]));
$records = $sth->fetchAll();

SQL query not equal to operator not working, with JOIN

I wonder if someone could help me with an SQL query.
I am trying to display all results except where in Table 2 both the userid column equals 1 and the hidden column equals 1.
I am basically trying to hide results from individual users based on their id and the value in the hidden column either 1 or empty.
I have so far managed to make a query that does the opposite and can't figure out how to change it. I have tried adding !=, <>, NOT and a few other things, but nothing is working for me!
Here is the query I am working with.
$stmt = $conn->prepare("SELECT tl.id, tl.name, tl.locale, uh.hidden
FROM theList AS tl
LEFT JOIN user_hidden_list AS uh ON uh.est_id = tl.id
WHERE uh.userid = '1' AND uh.hidden = '1'");
How do I display all results expect those with a uh.userid = 1 and uh.hidden = 1
UPDATE: Tables
Table: user_hidden_list
userid | Hidden | est_id
---------------------------
1 | 1 | 1
2 | 1 | 1
1 | 1 | 2
Table: theList
id | name | locale
------------------------
1 | Jacks | LDN
2 | MacD's | LDN
3 | BK | LDN
4 | Byron | LDN
So if I am logged in with and userid of:
1 I should see: BK and Byron.
2 I should see: MacD's, BK and Byron.
3 (or anything else) I should see: Jacks, MacD's, BK and Byron.
If i understood correctly, the table user_hidden_list mantains a relation between one user and the users he can't see. So for, example, user with id equal to 1 (matching on column userid) can't see users 1 and 2 (matching on column est_id).
So, for a particular user with ID = X, we can get the ID list of user he can't see like next:
SELECT
est_id
FROM
user_hidden_list
WHERE
userid = X AND hidden = 1;
Using the previous query, we can get the visible users for user X like on next query:
SELECT
tl.id, tl.name, tl.locale
FROM
theList AS tl
WHERE
tl.id NOT IN (SELECT est_id
FROM user_hidden_list
WHERE userid = X AND hidden = 1);
I'm sure there will be a better (elegant) way to do this, but i'm just leaving work and my mind is not working nice now.
I am trying to display all results except where in Table 2 both the userid column equals 1 and the hidden column equals 1.
This does not suggest an outer join. You seem to want:
SELECT tl.id, tl.name, tl.locale, uh.hidden
FROM theList tl JOIN
user_hidden_list uh
ON uh.est_id = tl.id
WHERE NOT (uh.userid = 1 AND uh.hidden = 1);
I am guessing that userid and hidden are numbers of some sort, so I removed the single quotes. If they are really strings, then use the single quotes.
This also assumes that these values cannot be NULL. If that is a possibility, then the logic can be adjusted (using the null-safe comparator <=>).
Try out this, with even parantheses:
SELECT tl.id, tl.name, tl.locale, uh.hidden
FROM theList tl JOIN
user_hidden_list uh
ON uh.est_id = tl.id
WHERE (uh.userid <> 1 AND uh.hidden <> 1);

Multiple leftJoins using Laravel's Query Builder producing incorrect counts

I am using Laravel 5.4's Query Builder to perform a series of leftJoins on three tables. Here are my tables:
items
id type title visibility status created_at
-- ---- ----- ---------- ------ ----------
1 1 This is a Title 1 1 2017-06-20 06:39:20
2 1 Here's Another Item 1 1 2017-06-24 18:12:13
3 1 A Third Item 1 1 2017-06-26 10:10:34
count_loves
id items_id user_id
-- ------- -------
1 1 2
2 1 57
3 1 18
count_downloads
id items_id user_id
-- ------- -------
1 1 879
2 1 323
And here is the code I am running in Laravel:
$items_output = DB::table('items')
->leftJoin('count_loves', 'items.id', '=', 'count_loves.items_id')
->leftJoin('count_downloads', 'items.id', '=', 'count_downloads.items_id')
->where('items.visibility', '=', '1')
->where('items.status', '=', '1')
->orderBy('items.created_at', 'desc')
->select('items.*', DB::raw('count(count_loves.id) as loveCount'), DB::raw('count(count_downloads.id) as downloadCount'))
->groupBy('items.id')
->get();
When I return the results for this query, I am getting the following counts:
count_loves: 6
count_downloads: 6
As you can see, the actual count values should be:
count_loves: 3
count_downloads: 2
If I add another entry to the count_loves table, as an example, the totals move to 8. If I add another entry to the count_downloads table after that, the totals jump to 12. So, the two counts are multiplying together.
If I die and dump the query, here's what I get:
"query" => "select 'items'.*, count(count_loves.id) as loveCount,
count(count_downloads.id) as downloadCount from 'items' left join
'count_loves' on 'items'.'id' = 'count_loves'.'items_id' left join
'count_downloads' on 'items'.'id' = 'count_downloads'.'items_id'
where 'items'.'visibility' = ? and 'items'.'status' = ? group by
'items'.'id' order by 'items'.'created_at' desc"
How do I perform multiple leftJoins using Query Builder and count on several tables to return the proper sums?
NOTE:
This is intended as a HELP answer not the total absolute answer but I could not write the code in a comment. I am not asking for votes (for those who just can't wait to downvote me). I have created your tables and tried a UNION query on raw sql. I got correct results. I dont have laravel installed, but maybe you could try a UNION query in Laravel.
https://laravel.com/docs/5.4/queries#unions
select count(count_downloads.user_id)
from count_downloads
join items
on items.id = count_downloads.items_id
UNION
select count(count_loves.user_id)
from count_loves
join items
on items.id = count_loves.items_id

Joining multiple tables returning 0 for specific column? PHP/MySQL

I'm having a problem at the moment where I have a column called rating in the links table and there is definitely values other than 0 within the column but 0 is the only value which is returned foreach link. When I do a simple get for that column it then shows all the other values but not when I do an SQL Join.
I know the problem is my joining of the tables but I'm unsure how I would go about joining these specific tables.
Database Table Structure
The rating column is the one which is causing me problems.
'links' id | title | url | user_id | list_id | rating | weight | date_created
'list' id | list_title | list_description | user_id | rating | views | date_created
'link_ratings' id | user_id | link_id | rated | date_created
Model:
public function get_latest(){
$this->db->limit(100);
$this->db->order_by('links.date_created', 'DESC');
$this->db->select('*');
$this->db->select('links.id as current_link_id');
$this->db->from('links');
$this->db->join('list', 'links.list_id = list.id');
$this->db->join('users', 'links.user_id = users.id');
$this->db->join('link_ratings', 'links.id = link_ratings.link_id','left');
$get_latest = $this->db->get();
return $get_latest;
}
Any Help is appreciated.
You should try this:
function get_latest(){
$this->db->select('list.*, users.*, links.id as current_link_id');
$this->db->from('links');
$this->db->join('list', 'links.list_id = list.id');
$this->db->join('users', 'links.user_id = users.id');
$this->db->join('link_ratings', 'links.id = link_ratings.link_id','left');
$this->db->order_by('links.date_created', 'DESC');
$this->db->limit(100);
$get_latest = $this->db->get()->result_array(); #fetch all rows here
echo "<pre>";print_r( $get_latest );die; #print all rows and see if its fetching ratings corrctly or not.
echo $this->db->last_query();die; #check the query generated
return $get_latest;
}
The reason will be purely logical, in that the join will be causing no results to be returned because there are no results. I've fallen into this many times.
I am not able to diagnose your particular problem but when faced with issues like this I:
1- turn on the CI profiler
2- var_dump the array so you can see what's going on
3- write a traditional SQL query and run it in PHPMyAdmin
One, or a combination of all three, will enable you to diagnose.

Error Doctrine Query when Using Group By

I'm using Symfony Project 1.4 and Postgresql
I got error query in doctrine using
$q = Doctrine_Query::create()
->select("count(sex) as total, sex")
->from('Biodata')
->groupBy('sex')
->execute();
there is always display error like this when debug:
SQLSTATE[42803]: Grouping error: 7 ERROR: column "e.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT e.id AS e__id, e.sex AS e__sex, COUNT(e.sex) AS e__0 ...
^. Failing Query: "SELECT e.id AS e__id, e.sex AS e__sex, COUNT(e.sex) AS e__0 FROM biodata e GROUP BY e.sex"
How to fix it and hide e.id column, is this bugs or need a trick?
Excepted result:
Doctrine automatically add the primary key to the select list. We've got the same error using MSSQL.
Try to add not hydrate result:
$q = Doctrine_Query::create()
->setHydrationMode(Doctrine_Core::HYDRATE_NONE)
->select("count(sex) as total, sex")
->from('Biodata')
->groupBy('sex')
->execute();
You won't have column name, but something like this I think:
+========+=========+
| 0 | 1 |
+========+=========+
| 183 | 1 |
+--------+---------+
| 54 | 2 |
+========+=========+

Categories