SELECT mairie.city, permission.permission
FROM permission , user_mairie, mairie
WHERE user_mairie.iduser = 1
AND user_mairie.idmairie = mairie.idmairie
CASE user_mairie.idrole
WHEN 2 THEN
JOIN user_permission
ON user_permission.idpermission = permission.idpermission
AND user_permission.iduser = user_mairie.iduser
END
ORDER BY mairie.idmairie, permission.idpermission
I'm trying to get the permissions of a specific user if this user has a specific role.
A "mairie" is a "town hall" in french.
A user can have different roles in different "mairie"s.
If the user on user_mairie has idrole = 2, then we have to go to the table "user_permission" to get it's permissions.
If the user on user_mairie has idrole = 1 then he is admin and he has ALL permissions, but the permissions are not written in user_permission (because user_permission is used only for idrole = 2).
What I want is for example :
if the user_mairie.idrole = 1 :
SELECT *
FROM permission
if the user_mairie.idrole = 2
SELECT *
FROM permission, user_permission
WHERE user_mairie.idrole = 2
AND user_mairie.iduser = user_permission.iduser
AND user_permission.idpermission = permission.idpermission
I could do this using my programming language and making 2 requests, but I'd like to know if in pure SQL, this issue is solvable.
Some datas:
Table permission:
idpermission | permission
1 | permission_1
2 | permission_2
3 | permission_3
Table user_mairie :
iduser | idmairie | idrole
1 | 1 | 1
1 | 2 | 2
Table user_permission :
iduser | idpermission | idmairie
1 | 1 | 2
1 | 3 | 2
Table mairie :
idmarie | city
1 | mairie_1
2 | mairie_2
The result I want (for a given iduser = 1) would be :
mairie_1 : permission_1, permission_2, permission_3
mairie_2 : permission_1, permission_3
Thanks for reading me.
SQL DEMO
First you start with all marie and all permissions
SELECT um.idrole, m.city, p.permission
FROM user_mairie um
JOIN mairie m
ON um.idmairie = m.idmairie
CROSS JOIN permission p
WHERE um.iduser = 1
Now you remove the permission you dont have
WHERE um.iduser = 1
AND ( um.idrole = 1 -- have all permission
OR EXISTS (SELECT up.idpermission
FROM user_permission up
WHERE up.iduser = um.iduser
AND up.idpermission = p.idpermission )
)
OUTPUT
I think you really want LEFT JOIN:
SELECT . . .
FROM user_mairie LEFT um
user_permission up
ON um.iduser = up.iduser LEFT JOIN
permission p
ON up.idpermission = p.idpermission OR
um.idrole = 1 ;
You may not want the condition on idrole.
This gets permissions only for id roles "2".
Notes:
List all the columns you want in the SELECT.
Learn to use proper, explicit, standard JOIN syntax. Never use commas in the FROM clause.
Table aliases make the query easier to write and to read.
Use LEFT JOIN so you can keep all the rows, even when there are no permissions.
Related
I have many tables with the same structure for each of my costumers.
All information are distinct for each table.
For some reason, I need to create some temporary table with the same structure with 200 values everytime I run.
So let's assume I have 3 tables.
Costumer1, Costumer2, Costumer3.
All those tables have id, user_name, contact_name, contact_email, sent1, sent2, sent3, sent4, status.
I need some query to put inside costumer_tmp, only 200 values in total, from all those 3 tables, everytime I run the script. And everytime I run cant repeat the last values I got before.
So for example:
Costumer1
id = 29
user_name = test1
contact_name = contact1
contact_email = contact1#mail.com
sent1 = yes
sent2 = no
sent3 = no
sent4 = no
status = In Progress
Costumer2
id = 37
user_name = test2
contact_name = contact123
contact_email = contact123#mail.com
sent1 = yes
sent2 = no
sent3 = no
sent4 = no
status = In Progress
Costumer3
id = 87
user_name = test3
contact_name = contact231
contact_email = contact231#mail.com
sent1 = yes
sent2 = no
sent3 = no
sent4 = no
status = In Progress
How to Insert on costumer_tmp only 2 records of those 3 and next time I run the script don't repeat those 2 records, just insert only 1 record remaining.
Your requirement is a bit weird, but if I understand weel, how about something like : (not tested)
insert into costumer_tmp
select * from Costumer1 one where one.id not in (select id from costumer_tmp)
union all
select * from Costumer2 two where two.id not in (select id from costumer_tmp)
union all
select * from Costumer3 three where three.id not in (select id from costumer_tmp) LIMIT 200
I have a statement I wish to execute to find if a column containing a string contains a certain value.
+----+------+
| id | st |
+----+------+
| 0 | 2183 |
| 1 | 5820 |
| 2 | 2984 |
| ...| ... |
+----+------+
Say I wish to find all rows where st contains a 1, I would use these where conditions:
WHERE st LIKE "%1%"
OR st LIKE "1%"
OR st LIKE "1"
OR st LIKE "%1"
But how do I do this in a prepared statement?
$ps = $db->prepare("
SELECT id
FROM table
WHERE st LIKE "%:a%"
OR st LIKE ":a%"
OR st LIKE ":a"
OR st LIKE "%:a"
");
$ps->execute(array(
':a' => $var
));
This doesn't work evidently.
The % sign must be part of $var not part of the prepared Statement. also you only need %:a% it include all other parts of your where clause
$ps = $db->prepare("
SELECT id
FROM table
WHERE st LIKE :a
");
$ps->execute(array(
':a' => "%".$var."%"
));
ps = $db->prepare("
SELECT id
FROM table
WHERE st LIKE :a");
$ps->execute(array(
':a' => "%".$var."%"
));
Try above code.
And one more thing if you require rows which contains 1 in it,then there is no requirement of 4 like condition you only can achieve using '%1%'.
Hope this will help.
I have the following query which takes more than 20 secs (20138ms) to return the results.
$locale = 'en'; // test
$query = $this->getEntityManager()->createQuery('
SELECT
product.id, product.productnr, ProductGrp.productgrp' . $locale . ', Criteria.criteria'.$locale.'
FROM
Productbundle:product product
JOIN
Productbundle:Criteria Criteria WITH Criteria.criteriaid = product.criteriaid
JOIN
Productbundle:ProductGrp ProductGrp WITH ProductGrp.partgrpid = product.partgrpid
WHERE
product.productnr =:productnr
')
->setMaxResults(1)
->setParameter('productnr', $productnr)
->getResult();
when I ran the query from "runnable query" it took about 20 secs (20.7809) in phpmyadmin.
runnable query :
SELECT o0_.id AS id0, o0_.productnr AS productnr1, o1_.productgrpen AS productgrpen2, o2_.criteriaen AS criteriaen3
FROM product o0_
INNER JOIN Criteria o2_ ON (o2_.criteriaid = o0_.criteriaid)
INNER JOIN ProductGrp o1_ ON (o1_.partgrpid = o0_.partgrpid)
WHERE o0_.productnr = 'ABC1234'
LIMIT 1;
However when I ran the following code in phpmyadmin it takes less than 2seconds to return the results
SELECT product.id, product.productnr,ProductGrp.productgrpen ,Criteria.criteriaen
FROM `product`
INNER JOIN ProductGrp ON ProductGrp.partgrpid = product.partgrpid
INNER JOIN Criteria ON Criteria.criteriaid = product.criteriaid
Where productnr = 'ABC1234'
LIMIT 1
table size
-------------------------------
|Product | over 5mill rows |
-------------------------------
|ProductGrp | over 200 rows |
-------------------------------
|Criteria | over 600 rows |
-------------------------------
Symfony version : 2.7
Indexes although not listed, I would suggest the following
table indexed on
Product (productnr, id, criteriaid, partgrpid )
Criteria (criteriaid ) -- would expect as primary key
ProductGrp (partgrpid ) -- also would expect
Also, how many "locale" string version columns do you have / support.
Need some help with a query.
In the database are ~700k of images, each image has it's own tag(s).
I want to be able to search images by it's tags with a full text search query.
The query does exactly what i want but it's very slow.
Can some please help me speed to speed it up, or create an other one.
There a indexes on al the id-fields and the name field in de 'image_tag' table.
SELECT
image.*
FROM image
INNER JOIN (SELECT image_to_tag.image_id,
GROUP_CONCAT(image_tag.`name`) AS tags
FROM image_to_tag
INNER JOIN image_tag
ON (image_tag.id = image_to_tag.image_tag_id)
GROUP BY image_to_tag.image_id) t ON t.image_id = image.id
WHERE MATCH (t.tags) AGAINST ('+justin* +backgrounds*' IN BOOLEAN MODE)
Table: image
id | filename
1 | image1.jpg
2 | image2.jpg
3 | image3.jpg
Table: image_to_tag
image_id | image_tag_id
1 | 1
1 | 2
2 | 3
2 | 4
Table: image_tag
id | name
1 | justin bieber
2 | backgrounds
3 | justin timberlake
4 | other backgrounds
If i search for "justin background" i want to find image 1 and 2.
If i search for "justin bieber background" i want to find image 1.
Please try this and let me know if with this could be a little faster.
select id,filename from image
where id in(
select image_id from image_to_tag a
inner join image_tag b
on b.id = a.image_tag_id and b.name like '%justin%'
)
You can boost up the performance by splitting your query into three parts. It will give your results in milliseconds :
$tagids = '';
$res = $mysqli->query("SELECT group_concat(id) as tagids FROM image_tag WHERE MATCH (name) AGAINST ('+justin* +backgrounds*' IN BOOLEAN MODE");
if($row = $res->fetch_object()){
$tagids = $row->tagids;
}
$res->close();
$imageids = '';
$res = $mysqli->query("SELECT group_concat(image_id) as imageids FROM image_to_tag WHERE image_tag_id in($tagids)");
if($row = $res->fetch_object()){
$imageids = $row->imageids;
}
$res->close();
$imgarr = array();
$res = $mysqli->query("SELECT id,filename FROM image WHERE id in($imageids)");
if($row = $res->fetch_object()){
array_push($imgarr,$row);
}
$res->close();
echo json_encode($imgarr);
I am trying to update my table 'supplier_stats' with the values from my other table 'supplier_change_request'.
My two tables look like the following:
Supplier_change_request
id | user_id | company_name | supplier_number
1 123 hewden V0001
Supplier_stats
Id | user_id | company_name | address | reference | supplier_number
1 123 pie n/a 12345 V0001
2 145 gates n/a 12345 V0002
Here is my MySQL:
$reference = '12345'
$query = "UPDATE supplier_stats
SET supplier_stats.company_name = (
SELECT supplier_change_request.company_name
FROM supplier_change_request
WHERE supplier_change_request.reference = '$reference' AND supplier_change_request.supplier_number = supplier_stats.supplier_number";
mysql_select_db('hewden1');
$retval = mysql_query( $query, $conn )
by my calculation this should be setting the value of company_name where supplier_number is 'V0001' in my table 'supplier_stats' to 'hewden'. However the company_name is not being updated.
Can someone please show me where I am going wrong? Thank you in advance
I think the syntax is a bit off in your query and that it should look like this (just the SQL, adapt to PHP as needed):
UPDATE supplier_stats ss
JOIN supplier_change_request scr ON scr.supplier_number = ss.supplier_number
SET ss.company_name = scr.company_name
WHERE ss.reference = '$reference'
The column reference pointed to the supplier_change_request in your sample query, but to supplier_stats in your sample data - I assumed the sample data was correct; change if not.
This query should change the company_name in supplier_stats from pie to hewden.