mySQL - WHERE, AND/OR selecting - mysql

I'm trying to select all posts from database, (where an ID is = an id from another table, which connects the people i'm in network with) OR (to select posts where i'm the writer of the post.). Actually i'm trying to get posts from people in my network AND my own.
I've found out how to do this, but when using the OR clause it's selecting the rows twice. So for example, if I write a post it's duplicated when echo'ed out from database.
My mySQL:
$sId = validate::intValidate($_SESSION['userId']);
$sql = "SELECT * FROM networkPost
INNER JOIN authentication
ON networkPost.FK_networkYou=authentication.userId
INNER JOIN network
ON networkPost.FK_networkYou=network.networkYou
WHERE networkMe=$sId AND FK_networkYou=networkYou OR networkYou=$sId
ORDER BY networkPostId DESC";
networkYou is: The userId of the post writer.
So how do I select my own posts and my networks posts?

You have few errors in your code
validate::intValidate($_SESSION['userId']); //missing square bracket
And the WHERE part of the query is missing brackets
WHERE (networkMe=$sId AND FK_networkYou=networkYou) OR networkYou=$sId

looks like you are missing '()'
$sId = validate::intValidate($_SESSION['userId');
$sql = "SELECT * FROM networkPost
INNER JOIN authentication
ON networkPost.FK_networkYou=authentication.userId
INNER JOIN network
ON networkPost.FK_networkYou=network.networkYou
WHERE (networkMe=$sId AND FK_networkYou=networkYou) OR networkYou=$sId
ORDER BY networkPostId DESC";

I found a solution on my problem. I wanna say thanks to Starx, which I might have pissed off, sorry! I'll make your answer the right one.
But here is my solution:
SELECT DISTINCT networkPost.*, authentication.* FROM networkPost
INNER JOIN authentication
ON networkPost.FK_networkYou=authentication.userId #Så jeg kan skrive hvem posteren er.
LEFT JOIN network
ON networkPost.FK_networkYou=network.networkYou
WHERE networkMe=$sId OR FK_networkYou=$sId
ORDER BY networkPostId DESC

Try this :
$sId = validate::intValidate($_SESSION['userId']);
$sql = "SELECT DISTINCT * FROM networkPost np,authentication at,network n
WHERE
np.FK_networkYou=n.networkYou AND
np.FK_networkYou=at.userId AND
np.FK_networkYou in(SELECT DISTINCT np.FK_networkYou FROM networkPost np,authentication at,network n
WHERE np.FK_networkYou=n.networkYou AND
np.FK_networkYou=at.userId AND
(networkMe=$sId AND FK_networkYou=networkYou) OR networkYou=$sId
ORDER BY networkPostId DESC");

Related

How to optimize a query with inner join

My mysql query is too slow and i don't know how to optimize it. My webapp cant load this query because take too much time to run and the webserver have a limit time to get the result.
SELECT rc.trial_id,
rc.created,
rc.date_registration,
rc.agemin_value,
rc.agemin_unit,
rc.agemax_value,
rc.agemax_unit,
rc.exclusion_criteria,
rc.study_design,
rc.expanded_access_program,
rc.number_of_arms,
rc.enrollment_start_actual,
rc.target_sample_size,
(select name from repository_institution where id = rc.primary_sponsor_id) as
primary_sponsor,
(select label from vocabulary_studytype where id = rc.study_type_id) as study_type,
(select label from vocabulary_interventionassigment where id =
rc.intervention_assignment_id) as intervention_assignment,
(select label from vocabulary_studypurpose where id = rc.purpose_id) as study_purpose,
(select label from vocabulary_studymasking where id = rc.masking_id) as study_mask,
(select label from vocabulary_studyallocation where id = rc.allocation_id) as
study_allocation,
(select label from vocabulary_studyphase where id = rc.phase_id) as phase,
(select label from vocabulary_recruitmentstatus where id = rc.recruitment_status_id) as
recruitment_status,
GROUP_CONCAT(vi.label)
FROM
repository_clinicaltrial rc
inner JOIN repository_clinicaltrial_i_code rcic ON rcic.clinicaltrial_id = rc.id JOIN
vocabulary_interventioncode vi ON vi.id = rcic.interventioncode_id
GROUP BY rc.id;
Using inner join instead join could be a solution?
Changing to JOINs vs continuous selects per every row will definitely improve. Also, since you are using MySQL, using the keyword "STRAIGHT_JOIN" tells MySQL to do the query in the order I provided. Since your "rc" table is the primary and all the others are lookups, this will make MySQL use it in that context rather than hoping some other lookup table be the basis of the rest of the joins.
SELECT STRAIGHT_JOIN
rc.trial_id,
rc.created,
rc.date_registration,
rc.agemin_value,
rc.agemin_unit,
rc.agemax_value,
rc.agemax_unit,
rc.exclusion_criteria,
rc.study_design,
rc.expanded_access_program,
rc.number_of_arms,
rc.enrollment_start_actual,
rc.target_sample_size,
ri.name primary_sponsor,
st.label study_type,
via.label intervention_assignment,
vsp.label study_purpose,
vsm.label study_mask,
vsa.label study_allocation,
vsph.label phase,
vrs.label recruitment_status,
GROUP_CONCAT(vi.label)
FROM
repository_clinicaltrial rc
JOIN repository_clinicaltrial_i_code rcic
ON rc.id = rcic.clinicaltrial_id
JOIN vocabulary_interventioncode vi
ON rcic.interventioncode_id = vi.id
JOIN repository_institution ri
on rc.primary_sponsor_id = ri.id
JOIN vocabulary_studytype st
on rc.study_type_id = st.id
JOIN vocabulary_interventionassigment via
on rc.intervention_assignment_id = via.id
JOIN vocabulary_studypurpose vsp
ON rc.purpose_id = vsp.id
JOIN vocabulary_studymasking vsm
ON rc.masking_id = vsm.id
JOIN vocabulary_studyallocation vsa
ON rc.allocation_id = vsa.id
JOIN vocabulary_studyphase vsph
ON rc.phase_id = vsph.id
JOIN vocabulary_recruitmentstatus vrs
ON rc.recruitment_status_id = vrs.id
GROUP BY
rc.id;
One final note. You are using a GROUP BY and applying to the GROUP_CONCAT() which is ok. However, proper group by says you need to group by all non-aggregate columns, which in this case is every other column in the list. You may know this, and the fact the lookups will be the same based on the "rc" associated columns, but its not good practice to do so.
Your joins and subqueries are probably not the problem. Assuming you have correct indexes on the tables, then these are fast. "Correct indexes" means that the id column is the primary key -- a very reasonable assumption.
My guess is that the GROUP BY is the performance issue. So, I would suggest structuring the query with no `GROUP BY:
select . . .
(select group_concat(vi.label)
from repository_clinicaltrial_i_code rcic
vocabulary_interventioncode vi
on vi.id = rcic.interventioncode_id
where rcic.clinicaltrial_id = rc.id
)
from repository_clinicaltrial rc ;
For this, you want indexes on:
repository_clinicaltrial_i_code(clinicaltrial_id, interventioncode_id)
vocabulary_interventioncode(id, label)

How can (SUM) in pivot table field and searching that field in yajra-laravel-datatable package (laravel 5.6)

! have three table
inventories
enter image description here
warehouses
enter image description here
inventory_has_warehouses
enter image description here
I have use laravel yajra datatable. i need sum and search of starting_balance this field in inventory_has_warehouses pivot table
my code:
$id = Auth::user()->id;
$row = Inventory::with('contact')->with('warehouse')
->select(
'inventories.*',
DB::raw('SUM(inventory_has_warehouses.starting_balance) as total')
)
->leftJoin('inventory_has_warehouses', 'inventory_has_warehouses.inventory_id', '=', 'inventories.id')
->leftJoin('warehouses', 'warehouses.id', '=', 'inventory_has_warehouses.warehouse_id')
->where('inventories.subscriber_id',$id)
->groupBy('inventories.id');
$datatable = DataTables::of($row)
->filterColumn('total', function($query, $keyword) {
$query->whereRaw('sum(inventory_has_warehouses.starting_balance) like ?', ['%'.$keyword.'%']);
})
return $datatable->make(true);
but i fount this type of error
Exception Message:↵↵SQLSTATE[HY000]: General error: 1111 Invalid use
of group function (SQL: select count() as aggregate from (select
inventories., SUM(inventory_has_warehouses.starting_balance) as
total from inventories left join inventory_has_warehouses on
inventory_has_warehouses.inventory_id = inventories.id left
join warehouses on warehouses.id =
inventory_has_warehouses.warehouse_id where
inventories.subscriber_id = 2 and inventories.status = 1 and
(LOWER(inventories.itemcode) LIKE %1% or
LOWER(inventories.purchasedescription) LIKE %1% or exists (select
* from contacts where inventories.supplier = contacts.id and LOWER(contacts.name) LIKE %1%) or
(sum(inventory_has_warehouses.starting_balance) like %1%)) group by
inventories.id) count_row_table)
mysql query
select inventories., SUM(inventory_has_warehouses.starting_balance)
as total from inventories left join inventory_has_warehouses on
inventory_has_warehouses.inventory_id = inventories.id left join
warehouses on warehouses.id = inventory_has_warehouses.warehouse_id
where inventories.subscriber_id = 2 and inventories.status = 1 and
(LOWER(inventories.itemcode) LIKE %1% or
LOWER(inventories.purchasedescription) LIKE %1% or exists (select *
from contacts where inventories.supplier = contacts.id and
LOWER(contacts.name) LIKE %1%) or
(sum(inventory_has_warehouses.starting_balance) like %1%)) group by
inventories.id
$id = Auth::user()->id;
$row = DB::table('inventories')->select('inventories.*','contacts.name',DB::raw('SUM(inventory_has_warehouses.starting_balance) as total'))
->leftJoin('contacts', 'inventories.supplier', '=', 'contacts.id')
->leftJoin('inventory_has_warehouses', 'inventories.id', '=', 'inventory_has_warehouses.inventory_id')
->where('inventories.subscriber_id',$id)
->groupBy('inventory_has_warehouses.inventory_id');
if ($keyword = $request->get('search')['value']) {
$row->having(DB::raw('SUM(inventory_has_warehouses.starting_balance)'), 'like', '%'.$keyword.'%');
$row->orHaving('inventories.itemcode', 'like', '%'.$keyword.'%');
$row->orHaving('inventories.purchasedescription', 'like', '%'.$keyword.'%');
$row->orHaving('contacts.name', 'like', '%'.$keyword.'%');
}
$datatable = DataTables::of($row)
->filterColumn('total', function($query, $keyword) {
})
return $datatable->make(true);
try to group by inventory_has_warehouses.inventory_id
Edited answer:
Your really giving hardtime for someone to read your query and give you help but to correct your query here is a reformatted query with corrections:
SELECT
inventories.*,
SUM(inventory_has_warehouses.starting_balance) as total
FROM
inventories LEFT JOIN inventory_has_warehouses
ON
inventory_has_warehouses.inventory_id = inventories.id LEFT JOIN warehouses
ON
warehouses.id = inventory_has_warehouses.warehouse_id
WHERE
inventories.subscriber_id = 2
AND
inventories.status = 1
AND
(LOWER(inventories.itemcode) LIKE '%1%' or LOWER(inventories.purchasedescription)
LIKE '%1%' OR EXISTS
(SELECT
*
FROM
contacts
WHERE
inventories.supplier = contacts.id
AND
LOWER(contacts.name) LIKE '%1%')
OR
(SUM(inventory_has_warehouses.starting_balance) LIKE '%1%')) GROUP BY inventories.id
the problem with query you sent is your like statement only have this:
LIKE %1%
this statement expects strings and it only says:
inventories.
this should be specific to a column you need or just use inventories.* to display all columns of that table but the error still doesn't make sense because it says and:
select count() as aggregate
maybe one of those would solve but upon reformatting your code I notice firstly the syntax error but this is very basic maybe you can start on just running a very simple query for the moment this might be the query that would work for you:
SELECT
inventories.id AS inventory_id,
warehouses.id,
SUM(inventory_has_warehouses.starting_balance) AS total
FROM
inventories LEFT JOIN inventory_has_warehouses
ON inventories.id = inventory_has_warehouses.inventory_id
LEFT JOIN
warehouses
ON warehouses.id = inventory_has_warehouses.warehouse_id
GROUP BY
inventory_has_warehouses.inventory_id
from this start adding the conditions one by one until the error appears again (do this on mysql query window not through laravel code) not yet sure how laravel handles sql queries but the format you sent will really cause an error and also if your going to post a question here make sure to make it reader friendly or someone might slam you cause its hard to read a code that is not properly formatted. ;)
also one thing I forgot make sure that the inventories.id is the primary key of that table or this will still cause you an error refer to this link for more details https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

convert following MySQL query into codeigniter

How to write this query in codeigniter
SELECT U.username,U.user_id
FROM storylikes S, user U
WHERE U.user_id=S.user_id_fk AND S.user_id_fk='$id'
try this :
$this->db->select('u.username, u.user_id');
db->where('u. user_id = s.user_id_fk');
$this->db->where('s.user_id_fk = '.$id);
$query = $this->db->get('storylikes s, user u');
use $your_variable = $query->result(); for the result
you should use joins instead of this query
$this->db->select('username,user_id');
$this->db->from('user');
$this->db->join('storylike','storylike.user_id_fk = user.user_id');
$this->db->where('storylike.user_id','$id');
as long as the db helper is loaded... You dont need to do anything special
$query = $this->db->query('SELECT U.username,U.user_id FROM storylikes S, user U WHERE U.user_id=S.user_id_fk AND S.user_id_fk=$id);
Using a cartesian (cross join) by doing FROM with 2 tables can cause some unruly results if not used 'correctly'
I suggest that if you are trying to just join tables together your SQL should be
SELECT U.username,U.user_id
FROM storylikes S, user U
INNER JOIN user U ON S.user_id = U.user_id_fk
WHERE S.user_id_fk=$id
CI querybuilder for this would be:
$query = $this->db->select('U.username,U.user_id')
->join('user U', 'S.user_id = U.user_id_fk', 'inner')
->where('S.user_id', $id)
->get('user U');
Using the correct join for the correct requirements is key;
INNER JOIN to ensure both FROM and the JOIN table match 1 for 1...
LEFT JOIN if you want to ensure you have all data from your FROM table and any without results in the JOIN table show up as NULL
RIGHT JOIN (opposite of left), to grab all data from the JOIN table and only matching data from the FROM table.
CROSS (CARTESIAN) JOIN when you want to ... frankly... mash the data together... A CROSS JOIN will also function like an INNER JOIN when you stipulate criteria in the WHERE statement (like you did) but still, use the correct JOIN for the correct usage-case.
There are other available joins but those are the basics.

Combining two columns on a id

this is my database
database schema http://slashdir.com/php/blogg/images/bloggdb.png
What i want to do, is, for a given userid, show the total times he has been reported.
I have read various other questions on the matter, but I'm still stumped.
The latest query i tried was
select
sum(posts.timesreported + comments.timesreported) AS total_reports
FROM
posts
INNER JOIN comments ON (posts.userid = comments.userid)
WHERE posts.userid=5 AND comments.userid=5;
But this must be wrong as the number i get is much too high
Thanks!
SELECT
CASE WHEN NULL
THEN 0
ELSE (select sum(posts.timesreported) AS total_posts_reports
FROM posts INNER JOIN users ON (posts.userid = users.id)
WHERE posts.userid=5)
END
+
CASE WHEN NULL
THEN 0
ELSE (select sum(comments.timesreported) AS total_comments_reports
FROM comments INNER JOIN users ON (comments.userid = users.id)
WHERE comments.userid=5)
END
FROM DUAL;
Instead of
sum(posts.timesreported + comments.timesreported) AS total_reports
try
sum(posts.timesreported) + sum(comments.timesreported) AS total_reports
and I think you need to group by userId
WHERE posts.userid=5 AND comments.userid=5; is unnecessary since the tables are joined.
And sum operator is not correct logically
Use this query
select
sum(posts.timesreported) + sum(comments.timesreported) AS total_reports
FROM
posts
INNER JOIN comments ON (posts.userid = comments.userid)
WHERE posts.userid=5
It looks like your collecting the sum PRIOR to singling out the user. Perhaps this is adding those column values for all users prior to the join? What happens if you SELECT *, perform your INNER JOIN where userid = 5. Save the column values as two variables and then try to add them. Do you get the same result?
This might help you error check to see if the above theory is accurate.
<?php
// Connects to your Database
mysql_connect("your.hostaddress.com", "username", "password") or die(mysql_error());
mysql_select_db("Database_Name") or die(mysql_error());
//Run Query
$NUM1=mysql_query("SELECT Field1 FROM Table WHERE user.key=5");
$NUM2=mysql_query("SELECT Field2 FROM Table WHERE user.key=5");
//Print Each Result
echo 'Num1 = '.$NUM1;
echo 'Num2 = '.$NUM2;
//Print Total
$TOTAL = $NUM1 + $NUM2;
echo 'Total = '.$TOTAL;
?>

mysql help...trouble returning data

On my website, I have a method that allows a logged in user to mark articles as a favourite, when logged in the articles are highlighted as being saved as a favourite, however if the user has no favourites, I cannot get the query to return any data, what is wrong with my query?
SELECT `job_id`,
COUNT(jobs.job_id) as jobs,
`employers`.`employer_id`,
`logo_small`, `logo_large`,
`company_name`, `job_tags`,
`favourite_employers`.`employer_id` AS employer
FROM (`employers`)
LEFT JOIN `jobs` ON `employers`.`employer_id` = `jobs`.`employer_id`
JOIN `favourite_employers` ON `favourite_employers`.`employer_id` = `jobs`.`employer_id`
WHERE `favourite_employers`.`user_id` = '2'
GROUP BY `jobs`.`employer_id`
ORDER BY `jobs`.`job_id` DESC
use LEFT JOIN instead of JOIN for the favourite_employers table
I know this may seem silly, but did you end the query with a ;?
It would be good to see the DB schema but you probably need a LEFT JOIN for favourite_employers.
The reason could be because this join:
JOIN `favourite_employers` ON `favourite_employers`.`employer_id` = `jobs`.`employer_id`
is returning nothing because there is no favorites