SQL JOIN query for Cakephp - mysql

I have 2 tables, one is called items, and the other is called sliders.
I want to call all the columns where sliders.item_id = items.id ,
and both are published so items.published=1 and sliders.published=1. But also I want to call sliders.item_id's that are NULL.
So basicly is like a right join where i get all related record that match the constrain but also records on the sliders table that don't correspond to items table.
In few words the point is this: i want to get ALL sliders that belongs to items (sliders.item_id=items.id) AND (sliders.published=1 AND items.published=1) BUT also sliders where item_id=null.
I have made a working query, but it does not satisfy me.
select *
from items
right join sliders
on items.id = 27
and items.id = sliders.item_id
and items.published = 1
where sliders.published = 1
THE TABLES
CREATE TABLE IF NOT EXISTS `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(30) NOT NULL,
`item_description` text NOT NULL,
`published` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `sliders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pic_path` text NOT NULL,
`item_id` int(11) DEFAULT NULL,
`published` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
First i want it in basic MySQL query because i can convert in cakephp later.

try this query,
SELECT *
FROM items
RIGHT JOIN sliders
ON items.id = sliders.item_id
WHERE items.published = 1 AND sliders.published = 1

when u got all record from table which are published from both :
$SQL = "SELECT *
FROM items
RIGHT JOIN sliders
ON items.id=sliders.id
WHERE items.published=1 AND sliders.published=1";
And when u want to get particular id record..
$id=27
$QRY = "SELECT *
FROM items
RIGHT JOIN sliders
ON items.id=sliders.id
WHERE items.published=1 AND sliders.published=1 AND items.id= $id";
and if you want to get more then one id records then...
$ids="27,28,29,30,50,55";
$QRY = "SELECT *
FROM items
RIGHT JOIN sliders
ON items.id=sliders.id
WHERE items.published=1 AND sliders.published=1 AND items.id in($ids)";
in last query u fetch records which is published in both table and id from the above.

Related

Trying to join multiple tables in mysql - get error 1054, Unknown Column

I want to join multiple tables using JOINs, and mysql/mariadb is refusing to find one column. The column exists, of course, and I can't figure out what the cause might be.
Table Layout
CREATE TABLE `shops` (
`id` int(11) NOT NULL,
`name` varchar(32) NOT NULL,
);
CREATE TABLE `shops2categories` (
`shopid` int(11) NOT NULL,
`categoryid` int(11) NOT NULL,
);
CREATE TABLE `categories` (
`id` int(11) NOT NULL,
`name` varchar(64) NOT NULL,
);
CREATE TABLE `categories2items` (
`itemid` int(11) NOT NULL,
`categoryid` int(11) NOT NULL
);
CREATE TABLE `items` (
`id` int(11) NOT NULL,
`name` varchar(32) NOT NULL,
);
Query:
In order to avoid confusion with aliases, I now ran the query with the original table names.
SELECT
shops.name,
categories.name,
items.name
FROM shops
LEFT JOIN shops2categories ON shops2categories.shopid = shops.id
LEFT JOIN categories2items ON categories2items.categoryid = categories.id
LEFT JOIN categories ON categories.id = shops2categories.categoryid
LEFT JOIN items ON items.id = categories2items.itemid
Error Message:
#1054 - Unknown column 'categories.id' in 'on clause'
No matter how I restructured my query (foreign key first, primary key first, items table first, categories table first, ..., using different JOIN types), I can't seem to get this to work. Also I read through a whole lot of SO questions to this topic, but I feel that the order is correct, I am not inserting nor updating, and it's not about quoting. Something is fundamentally broken in my concept, and I'm very keen on learning what this could be.
Look at your from clause. You reference c.id before you have defined c.
A table cannot be referenced until it is defined in the FROM clause.
You would seem to want:
FROM shops s LEFT JOIN
shops2categories s2c
ON s2c.shopid = s.id LEFT JOIN
categories c
ON c.id = s2c.categoryid LEFT JOIN
categories2items c2i
ON c2i.categoryid = c.id LEFT JOIN
items i
ON i.id = c2i.itemid

Insert into with multi select or multi conditions

I have a table that contains many informations:
CREATE TABLE sequences (
`id` INT(11) NOT NULL DEFAULT '0',
`name` TEXT NULL,enter code here
`nbrlsu` BIGINT(20) NULL DEFAULT NULL,
`nbrits` BIGINT(20) NULL DEFAULT NULL,
`nbrco1` BIGINT(20) NULL DEFAULT NULL,
`nbrrcbl` BIGINT(20) NULL DEFAULT NULL,
`nbrmatk` BIGINT(20) NULL DEFAULT NULL,
`nbrsequences` BIGINT(20) NULL DEFAULT NULL,
`parent_id` BIGINT(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
I want to create a table based on sum of columns in the first table
for exemple I want to know te number of elements that have the same parent_id and has numbersequences>0
and I want to know for each type of sequences the number of rows that contains information:
SELECT parent_id ,
Classification,count(id) as nbrspecies,
SUM(nbrsequences) ,
SUM(nbrco1),
SUM(nbrits),
SUM(nbrlsu),
SUM(nbrrcbl),
SUM(nbrmatk)
FROM dashboard_specimen
GROUP BY parent_id
and I have an other kind of queries:
SELECT parent_id ,
count(id) as co1
FROM dashboard_specimen
WHERE nbrco1>0
GROUP BY parent_id ;
and
SELECT parent_id ,
count(id) as nbrspecies
FROM dashboard_specimen
WHERE nbrsequences>0
GROUP BY parent_id
and other types like this
and my goal in the end is to insert this information into an other table with insert select
like this:
INSERT INTO bold_namestats (id,
name,
numberofstrains,
numberofsequences,
numberofco1,
numberofits,
numberoflsu,
numberofrbcl,
numberofmatk)
SELECT parent_id ,
Classification,
count(id) as nbrspecies,
SUM(nbrsequences) ,
SUM(nbrco1),
SUM(nbrits),
SUM(nbrlsu),
SUM(nbrrcbl),
SUM(nbrmatk)
FROM dashboard_specimen
GROUP BY parent_id
I don't know if there is a simple way to do this with temp tables or something like this
If I understand well, you could do a subquery for each column you want to populate, filtering each subquery for an id.
INSERT INTO bold_namestats (id,
name,
numberofstrains,
numberofsequences,
numberofco1,
numberofits,
numberoflsu,
numberofrbcl,
numberofmatk)
select parent_id, (*select1* where parent_id=...), (*select2* where parent_id=...), ... , (*selectn* where parent_id=...)
from dashboard_specimen
group by parent_id
where select1, select2, ... , selectn are the different queries you have.
Finally I have resolved my problem using join and temp tables
INSERT INTO bold_namestats (_id,numberofstrains, numberofsequences,numberofco1,numberofits,numberoflsu,numberofrbcl,numberofmatk,numberstrainswithco1,numberstrainswithseq)
SELECT a._id ,a.numberofstrains,a.numberofsequences ,a.numberofco1,a.numberofits,a.numberoflsu,a.numberofrbcl,a.numberofmatk,b.numberofstrainswithco1,c.numberofstrainswithseq FROM bold_temp_namestats a left join bold_strainswithco1 b on a._id=b.parent_id left join bold_strainswithseq c on a._id=c.parent_id union
SELECT a._id ,a.numberofstrains,a.numberofsequences ,a.numberofco1,a.numberofits,a.numberoflsu,a.numberofrbcl,a.numberofmatk,b.numberofstrainswithco1,c.numberofstrainswithseq FROM bold_temp_namestats a right join bold_strainswithco1 b on a._id=b.parent_id left join bold_strainswithseq c on a._id=c.parent_id ;
this query is used to replace full outer join so I fill 3 tables with data and after that I insert with joinin result with left and right join and union the result to get full lines in the end

How would I get articles from a certain category and its children?

I'm developing an article system that uses categories and child categories.
Basically, if the category has a parent_id value, it's a child of that category.
I would like to be able to get the most recent articles from a category and articles from its child categories.
For example: I have a category called "Gaming Articles" and several child categories under that called Xbox, PlayStation, Nintendo, and PC. My system makes it possible to post articles in the parent categories such as Gaming Articles as well as in the child categories.
So this would have to include articles that are in either the parent category or the child categories of that parent.
CREATE TABLE IF NOT EXISTS `articles` (
`article_id` int(15) NOT NULL AUTO_INCREMENT,
`author_id` int(15) NOT NULL,
`category_id` int(15) NOT NULL,
`modification_id` int(15) NOT NULL,
`title` varchar(125) NOT NULL,
`content` text NOT NULL,
`date_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`status` tinyint(1) NOT NULL,
`attachment_id` int(15) NOT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `article_categories` (
`category_id` int(15) NOT NULL AUTO_INCREMENT,
`parent_id` int(15) NOT NULL,
`title` varchar(50) NOT NULL,
`description` text NOT NULL,
`attachment_id` text NOT NULL,
`enable_comments` tinyint(1) NOT NULL,
`enable_ratings` tinyint(1) NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The query I have so far...
SELECT article_id, category_id
FROM articles
WHERE category_id = 1
ORDER BY article_id DESC
LIMIT 10
Of course, this only gets articles under that category, not from both the category and that category's child categories.
As your table structure stands, this query will work assuming only 1 level of nesting (ie children don't themselves have children):
SELECT a.*
FROM articles a
JOIN article_categories ac ON a.category_id = ac.category_id
WHERE 1 IN (a.category_id, ac.parent_id)
ORDER BY a.article_id DESC
LIMIT 10
Note the "reversed" style IN to neatly capture what is effectively an OR.
If your nesting is deeper, simply add another join for each level, for example if you have up to 4 levels (2 more than the above query):
SELECT a.*
FROM articles a
JOIN article_categories ac1 ON a.category_id = ac1.category_id
LEFT JOIN article_categories ac2 ON ac1.parent_id = ac2.category_id
LEFT JOIN article_categories ac3 ON ac2.parent_id = ac3.category_id
WHERE 1 IN (a.category_id, ac1.parent_id, ac2.parent_id, ac3.parent_id
ORDER BY a.article_id DESC
LIMIT 10
In the second case, the use of left joins is necessary to still return articles that don't have so many levels above.
In this structure is inposible in one query. (I assume that there are many levels of categories)
You can:
recursively search child categories (ex. in php) and then
SELECT * FROM articles WHERE category_id IN ( $categories );
change db structure and use tree structure
try: The Nested Set Model in article : http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
add new column to categories table, and store full path to category, ex.:
category 1->2, category_path 1,2
category 1->2->3, category_path 1,2,3
category 1->4, new category_path 1,4
If You looking all data in category 1 and children, try:
SELECT
a.*
FROM articles a
INNER JOIN categories c
ON a.category_id = c.category_id
WHERE c.category_path LIKE '1,%'
As far as i understand, what you want is to get all the articles from a child of a category, if that is correct, try this out:
SELECT a.article_id, a.category_id FROM articles as a, article_categories c WHERE a.category_id = c.category_id AND c.parent_id = (SELECT c.parent_id WHERE c.category_id = 1) ORDER BY article_id DESC LIMIT 10
If this wasn't what you wanted, comment it, i'll try to answer you.

MySQL query for parent and child table

I need help writing a mysql query. I have two tables, one parent, one child.
Parent table: garments
`garment_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` text,
PRIMARY KEY (`garment_id`)
Child table: garment_images
`id` int(11) NOT NULL AUTO_INCREMENT,
`garment_id` int(11) NOT NULL,
`filename` varchar(100) NOT NULL,
`order` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
I would like query all garments, and to show the first image for each item from the 'garment_images' table.
This should be fairly close:
SELECT G.*, (
SELECT GI.id, GI.filename from garment_images as GI
WHERE GI.garment_id = G.garment_id
ORDER BY GI.order DESC
LIMIT 1)
FROM garments as G
Split the problem:
Retreive the first image id for every garment
Put the data together
Step 1:
select gi.*
from
garment_images as gi
inner join (
select min(id) as minId
from garment_images
group by garment_id
) as a on gi.garment_id = a.minId
I'll leave to you the second step (Hint: join the data from the query above with your garment table)
If "the first image" is the one with order = 1 (SQL Fiddle)
SELECT * from garments g JOIN garment_images gi
ON g.garment_id = gi.garment_id
WHERE gi.order = 1

mysql query with multiple groups?

I have a query that gets product IDs based on keywords.
SELECT indx_search.pid
FROM indx_search
LEFT JOIN word_index_mem ON (word_index_mem.word = indx_search.word)
WHERE indx_search.word = "phone"
GROUP BY indx_search.pid
ORDER BY indx_search.pid ASC
LIMIT 0,20
This works well but now I'm trying to go a step further and implement "price range" into this query.
CREATE TABLE `price_range` (
`pid` int(11) NOT NULL,
`range_id` tinyint(3) NOT NULL,
PRIMARY KEY (`pid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
This table simply contains product IDs and a range_id. The price range values are stored here:
CREATE TABLE `price_range_values` (
`ID` tinyint(3) NOT NULL AUTO_INCREMENT,
`rangeFrom` float(10,2) NOT NULL,
`rangeTo` float(10,2) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=latin1
I want to GROUP price_range.range_id with COUNT() of how many products match the certain price range within the current query. I still want to receive my 20 results of product IDs.
So something along the lines of:
SELECT indx_search.pid, price_range.range_id as PriceRangeID, COUNT(price_range.range_id) as PriceGroupTotal
FROM indx_search
LEFT JOIN windex_mem ON ( windex_mem.word = indx_search.word )
LEFT JOIN price_range ON ( price_range.pid = indx_search.pid )
WHERE indx_search.word = "memory"
GROUP BY indx_search.pid, PriceRangeID
ORDER BY indx_search.pid ASC
LIMIT 0 , 20
Is this possible to accomplish without busting an additional query?
Try to use a subquery with a LIMIT clause, e.g. -
SELECT
i_s.pid, p_r.range_id as PriceRangeID, COUNT(p_r.range_id) as PriceGroupTotal
FROM
(SELECT * FROM indx_search WHERE i_s.word = 'memory' ORDER BY i_s.pid ASC LIMIT 0 , 20) i_s
LEFT JOIN
windex_mem w_m ON w_m.word = i_s.word
LEFT JOIN
price_range p_r ON p_r.pid = i_s.pid
GROUP BY
i_s.pid, PriceRangeID