mysql- table comparison error - mysql

I have 2 tables, CAR_1 and CAR_2. Table CAR_1 contains more columns and more records than CAR_2.
Running the query below returns 4647 records:
(SELECT CAR_1.ID FROM CAR_1, CAR_2 WHERE
CAR_1.ID = CAR_2.ID AND
CAR_1.MODEL = CAR_2.MODEL AND
CAR_1.SYMBOL = CAR_2.SYMBOL AND
CAR_1.MAKE = CAR_2.MAKE AND
CAR_1.ORIGIN = CAR_2.ORIGIN) AS table_all
While running the same query without the last 2 columns comparison returns 4600 records.
(SELECT CAR_1.ID FROM CAR_1, CAR_2 WHERE
CAR_1.ID = CAR_2.ID AND
CAR_1.MODEL = CAR_2.MODEL AND
CAR_1.SYMBOL = CAR_2.SYMBOL ) AS table_min
I would like to to get the 47 records whose make and origin are different, so i tried the sql below but it does not seem to be working properly
select * from (SELECT CAR_1.ID FROM CAR_1, CAR_2 WHERE
CAR_1.ID = CAR_2.ID AND
CAR_1.MODEL = CAR_2.MODEL AND
CAR_1.SYMBOL = CAR_2.SYMBOL AND
CAR_1.MAKE = CAR_2.MAKE AND
CAR_1.ORIGIN = CAR_2.ORIGIN) AS table_all
WHERE NOT EXISTS(
(SELECT CAR_1.ID FROM CAR_1, CAR_2 WHERE
CAR_1.ID = CAR_2.ID AND
CAR_1.MODEL = CAR_2.MODEL AND
CAR_1.SYMBOL = CAR_2.SYMBOL ) AS table_min
WHERE table_all.ID = table_min.ID
)
I would appreciate it if someone can show me the error

Isn't it as simple as:
SELECT
CAR_1.ID
FROM
CAR_1, CAR_2
WHERE
CAR_1.ID = CAR_2.ID AND
CAR_1.MODEL = CAR_2.MODEL AND
CAR_1.SYMBOL = CAR_2.SYMBOL AND
(CAR_1.MAKE <> CAR_2.MAKE OR CAR_1.ORIGIN <> CAR_2.ORIGIN);
?

SELECT CAR_1.ID FROM CAR_1
outer join CAR_2 On
CAR_1.ID = CAR_2.ID
AND CAR_1.MODEL = CAR_2.MODEL
AND CAR_1.SYMBOL = CAR_2.SYMBOL
AND CAR_1.MAKE = CAR_2.MAKE
AND CAR_1.ORIGIN = CAR_2.ORIGIN
Where Car2.id is null
Will give you the id's of all cars in car1 with no matching record in Car2
More efficient than exists, or not in subqueries.

Related

Multiple rows in a select with OR

I have this query and when I add a OR, return multiples rows, how I can fix this? I need another left join or Right join?
SELECT `images`.`id` as `id_image`, `images_lang`.`title` as `title`, `images_lang`.`autor` as `author`, `media_lang`.`file`, `category_lang`.`title` as `category`
FROM `images`
JOIN `images_lang` ON `images_lang`.`id_images` = `images`.`id`
JOIN `category_lang` ON `images`.`id_category` = `category_lang`.`id_category`
JOIN `media` ON `images`.`id` = `media`.`id_item`
JOIN `media_lang` ON `media`.`id` = `media_lang`.`id_media`
JOIN `relation` ON `relation`.`from_id` = `images`.`id`
JOIN `tag` ON `tag`.`id` = `relation`.`to_id`
JOIN `tag_lang` ON `tag`.`id` = `tag_lang`.`id_lang`
WHERE `media`.`table` = 'images'
AND `media_lang`.`id_lang` = '1'
AND `images_lang`.`id_lang` = '1'
AND `category_lang`.`id_lang` = '1'
AND `images`.`active` = 1
AND `relation`.`type` = 2
AND `tag_lang`.`id_lang` = '1'
AND `tag_lang`.`slug` = 'pa-am-oli'
OR `tag_lang`.`slug` = 'playa'
LIMIT 9
and the code in codeigniter, but I donĀ“t how add the or after the and ($keywords is an array for filter the elements)
$this->db->select('images.id as id_image, images_lang.title as title, images_lang.autor as author, media_lang.file, category_lang.title as category');
$this->db->from($this->table);
$this->db->join($this->table.'_lang',$this->table.'_lang.id_images = '.$this->table.'.id');
$this->db->join('category_lang',$this->table.'.id_category = category_lang.id_category');
$this->db->join('media',$this->table.'.id = media.id_item');
$this->db->join('media_lang','media.id = media_lang.id_media');
$this->db->where('media.table',$this->table);
$this->db->where('media_lang.id_lang',$id_lang);
$this->db->where($this->table.'_lang.id_lang', $id_lang);
$this->db->where('category_lang.id_lang', $id_lang);
$this->db->where('images.active', 1);
if($category){
$this->db->where('category_lang.title', $category);
}
if($keywords){
$this->db->join('relation', 'relation.from_id = '.$this->table.'.id');
$this->db->join('tag', 'tag.id = relation.to_id');
$this->db->join('tag_lang', 'tag.id = tag_lang.id_lang');
$this->db->where('relation.type', _IMAGES_2_TAGS_);
$this->db->where('tag_lang.id_lang', $id_lang);
foreach($keywords as $tag){
$this->db->or_where('tag_lang.slug', $tag);
}
}
if($from || $limit)
{
$this->db->limit((int)$limit, (int)$from);
}
$query = $this->db->get();
return $query->result_array();
I solved the query adding this (and a Select Distinct)
AND (`tag_lang`.`slug` = 'playa'
OR `tag_lang`.`slug` = 'pa-am-oli')
How I can add this in codeigniter?
I don't get what you need exactly, but if you want have just one line as a return by filtering using OR
In your case you should do the following:
WHERE (`media`.`table` = 'images' OR `tag_lang`.`slug` = 'playa')
AND (`media_lang`.`id_lang` = '1' OR `tag_lang`.`slug` = 'playa')
and so on, I hope that helps you and good luck!
Astute use of parentheses would solve your problem, but this is easier to read...
SELECT i.id id_image
, il.title
, il.autor author
, ml.file
, cl.title category
FROM images i
JOIN images_lang il
ON il.id_images = i.id
JOIN category_lang cl
ON cl.id_category = i.id_category
JOIN media m
ON m.id_item = i.id
JOIN media_lang ml
ON ml.id_media = m.id
JOIN relation r
ON r.from_id = i.id
JOIN tag t
ON t.id = r.to_id
JOIN tag_lang tl
ON tl.id_lang = t.id
WHERE m.table = 'images'
AND ml.id_lang = 1
AND il.id_lang = 1
AND cl.id_lang = 1
AND i.active = 1
AND r.type = 2
AND tl.id_lang = 1
AND tl.slug IN('pa-am-oli','playa')
LIMIT 9
... however, note that LIMIT without ORDER BY is fairly meaningless.

conditional sql query for range of results

I have a query that I want to show results differently depending on a specific field. For example, I am using
$result = $wpdb->get_results( "SELECT `b`.`company` AS `company`,`bp`.`material` AS `material`,
if(((`bp`.`cost` * 1.2) < `ls`.`maximumbid`),(ROUND(`bp`.`cost` * 1.2,2)),ROUND(`bp`.`cost`,2)) AS `newcost`
from (((`windows_brands_products` `bp` left join `windows_brands` `b` on((`bp`.`brand_id` = `b`.`id`)))
join `Windows_last_submissions` `ls`) join `windows_materials` `wm`)
where ((`bp`.`width` = round(`ls`.`width`,0))
and (`bp`.`height` = round(`ls`.`height`,0))
and (`bp`.`material` = `wm`.`name`)
and (`bp`.`type` = `ls`.`type`)
and if((`ls`.`minimumbid` <> '0.00'),(`bp`.`cost` between `ls`.`minimumbid` and `ls`.`maximumbid`),(`bp`.`cost` <= `ls`.`maximumbid`)))
ORDER BY b.company ASC");
The results I want are if the row ls.type = 'Fixed/Picture', I want bp.width = round(ls.width,-1) and still as I have it for any other ls.type
I should be getting correct results from:
select `b`.`company` AS `company`,`bp`.`material` AS `material`,if(((`bp`.`cost` * 1.2) < `ls`.`maximumbid`),round((`bp`.`cost` * 1.2),2),round(`bp`.`cost`,2)) AS `newcost` from (((`windows_brands_products` `bp` left join `windows_brands` `b` on((`bp`.`brand_id` = `b`.`id`))) join `Windows_last_submissions` `ls`) join `windows_materials` `wm`)
where if((`ls`.`type` = 'Fixed/Picture'),(`bp`.`width` = round(`ls`.`width`,-2),(`bp`.`width` = round(`ls`.`width`,0)) and (`bp`.`height` = round(`ls`.`height`,0)) and (`bp`.`material` = `wm`.`name`) and (`bp`.`type` = `ls`.`type`) and if((`ls`.`minimumbid` <> '0.00'),(`bp`.`cost` between `ls`.`minimumbid` and `ls`.`maximumbid`),(`bp`.`cost` <= `ls`.`maximumbid`))) order by `b`.`company`
but it keeps giving me syntax errors as I try to correct the query which I'm not succeeding.
The point is retrieve a broader range of results if the type is 'Fixed/Picture'
Thank you,
Casey

Obtain value from same column twice with different condition in single query

Hii I want to Obtain value from same column twice with different condition in single query
Here is my code
SELECT
o.products_options_name,
ov.products_options_values_name AS products_options_values_name,
a.options_values_quantity
FROM
table_products_options o,
table_products_attributes a
WHERE
a.options_id = o.products_options_id
AND
o.products_options_values_id = a.options_values_id
AND
a.products_id = :products_id
AND
a.options2_values_id = options2_values_id
i want to obtain value of column products_options_values_name again with different condition like where a.options2_values_id = ov.products_options_values_id in same query. How can i do this?
try by using UNION operator,
SELECT o.products_options_name, ov.products_options_values_name AS products_options_values_name,
a.options_values_quantity
FROM
table_products_options o, table_products_attributes a
WHERE
a.options_id = o.products_options_id AND ov.products_options_values_id = a.options_values_id
AND a.products_id = :products_id1 AND
a.options2_values_id = options2_values_id
UNION
SELECT o.products_options_name, ov.products_options_values_name AS products_options_values_name,
a.options_values_quantity
FROM
table_products_options o, table_products_attributes a
WHERE
a.options_id = o.products_options_id AND ov.products_options_values_id = a.options_values_id
AND a.products_id = :products_id2 AND
a.options2_values_id = options2_values_id
Union / Union all would be best
like
select o.products_options_name, ov.products_options_values_name as
products_options_values_name, a.options_values_quantity
from
table_products_options o, table_products_attributes a
where
a.options_id = o.products_options_id and ov.products_options_values_id =
a.options_values_id and a.products_id = :products_id and a.options2_values_id =
options2_values_id
UNION
select o.products_options_name, ov.products_options_values_name as products_options_values_name, a.options_values_quantity
from
table_products_options o, table_products_attributes a
where Diffrent Clause
Union Works like Distinct, Union ALL will return duplicate values if your clauses both return the value.
Alternatively use OR in your where clause and (a.b = c.d OR c.d=b.a) and
You can specify the condition that you want in the on clause. on clause? Your query should use explicit join syntax.
Here is one way to express the query that you want:
select o.products_options_name, ov.products_options_values_name as products_options_values_name,
a.options_values_quantity
from table_products_options o join
table_products_attributes a
on a.options_id = o.products_options_id and
(ov.products_options_values_id = a.options_values_id or
a.options2_values_id = options2_values_id
)
where a.products_id = :products_id;

Update mysql table with data from multiple tables

I have the following query and I would like to make it so if there's a duplicate key it updates the values
INSERT INTO totalData (pageId, dateScanned, totalPageLikes, totalTalkingAbout, totalPos, totalNeg, totalFemales, totalMales, totalStrongPositives, totalPositives, totalWeakPositives, totalNeutrals, totalWeakNegatives, totalNegatives, totalStrongNegatives, totalStatuses, totalStatusLikes, totalStatusShares, totalComments, totalUniqueCommenters)
SELECT pages.pageId, pages.dateScanned, pages.likes, pages.talkingAbout,
SUM(commentTags.tag LIKE '%positive%') AS positive,
SUM(commentTags.tag LIKE '%negative%') AS negative,
SUM(comments.gender = 'female') AS females,
SUM(comments.gender = 'male') AS males,
SUM(commentTags.tag = 'strong_positive') AS strongPositives,
SUM(commentTags.tag = 'positive') AS positives,
SUM(commentTags.tag = 'weak_positive') AS weakPositives,
SUM(commentTags.tag = 'neutral') AS neutrals,
SUM(commentTags.tag = 'weak_negative') AS weakNegatives,
SUM(commentTags.tag = 'negative') AS negatives,
SUM(commentTags.tag = 'strong_negative') AS strongNegatives,
COUNT(DISTINCT statuses.statusId) AS totalStatuses,
SUM(DISTINCT statuses.likesCount) AS totalLikesCount,
SUM(DISTINCT statuses.sharesCount) AS totalSharesCount,
COUNT(DISTINCT comments.commentId) AS totalComments,
COUNT(DISTINCT comments.userName) AS uniqueUsers
FROM pages
JOIN statuses ON pages.pageId = statuses.pageId AND pages.dateScanned = statuses.dateScanned
JOIN comments ON comments.statusID = statuses.statusId
JOIN commentTags ON comments.commentId = commentTags.commentId
WHERE pages.pageId = '115798033817' AND pages.dateScanned = '2013-11-05'
I tried the ON DUPLICATE KEY UPDATE and this is how I further modified the query
ON DUPLICATE KEY UPDATE
totalData.pageId = pageId, totalData.dateScanned = dateScanned,
totalData.totalPageLikes = totalPageLikes, totalData.totalTalkingAbout = totalTalkingAbout,
totalData.totalPos = positive, totalData.totalNeg = negative, totalData.totalFemales = females,
totalData.totalMales = males, totalData.totalStrongPositives = strongPositives,
totalData.totalPositives = positives, totalData.totalWeakPositives = weakPositives,
totalData.totalNeutrals = neutrals, totalData.totalWeakNegatives = weakNegatives,
totalData.totalNegatives = negatives, totalData.totalStrongNegatives = strongNegatives,
totalData.totalStatuses = totalStatuses, totalData.totalStatusLikes = totalLikesCount,
totalData.totalStatusShares = totalSharesCount, totalData.totalComments = totalComments,
totalData.totalUniqueCommenters = uniqueUsers ;
But when i run the query it says Unknown column 'positive' in field list.
Got it, I had to use the VALUES() function so the ON DUPLICATE KEY UPDATE part of the query becomes like the following
ON DUPLICATE KEY UPDATE
totalPageLikes = VALUES(totalPageLikes), totalTalkingAbout = VALUES(totalTalkingAbout),
totalPos = VALUES(totalPos), totalNeg = VALUES(totalNeg), totalFemales = VALUES(totalFemales), totalMales = VALUES(totalMales),
totalStrongPositives = VALUES(totalStrongPositives), totalPositives = VALUES(totalPositives), totalWeakPositives = VALUES(totalWeakPositives),
totalNeutrals = VALUES(totalNeutrals), totalWeakNegatives = VALUES(totalWeakNegatives), totalNegatives = VALUES(totalNegatives), totalStrongNegatives = VALUES(totalStrongNegatives),
totalStatuses = VALUES(totalStatuses), totalStatusLikes = VALUES(totalStatusLikes), totalStatusShares = VALUES(totalStatusShares),
totalComments = VALUES(totalComments), totalUniqueCommenters = VALUES(totalUniqueCommenters) ";

MySQL Subquery Efficiency

I have this query which adds a load of values to a 'stats' table. When the query runs it selects the values to fill the table in subqueries. I was wondering if this could be made any more efficiently or if I am doing something really wrong. I am not that familiar with MySQL so any help would be great :)
Here is the query:
UPDATE mediastats SET
mediastats_members = (SELECT count(*) FROM status WHERE status_media_id = :id),
mediastats_avscore = (SELECT AVG(status_rating) FROM status WHERE status_media_id = :id),
mediastats_done = (SELECT count(*) FROM status WHERE status_status = 'done' AND status_media_id = :id),
mediastats_doing = (SELECT count(*) FROM status WHERE status_status = 'doing' AND status_media_id = :id),
mediastats_redoing = (SELECT count(*) FROM status WHERE status_status = 'redoing' AND status_media_id = :id),
mediastats_dropped = (SELECT count(*) FROM status WHERE status_status = 'dropped' AND status_media_id = :id),
mediastats_wantto = (SELECT count(*) FROM status WHERE status_status = 'wantto' AND status_media_id = :id),
mediastats_wont = (SELECT count(*) FROM status WHERE status_status = 'wont' AND status_media_id = :id),
mediastats_stalled = (SELECT count(*) FROM status WHERE status_status = 'stalled' AND status_media_id = :id),
mediastats_rating_1 = (SELECT count(*) FROM status WHERE status_rating = 1 AND status_media_id = :id),
mediastats_rating_2 = (SELECT count(*) FROM status WHERE status_rating = 2 AND status_media_id = :id),
mediastats_rating_3 = (SELECT count(*) FROM status WHERE status_rating = 3 AND status_media_id = :id),
mediastats_rating_4 = (SELECT count(*) FROM status WHERE status_rating = 4 AND status_media_id = :id),
mediastats_rating_5 = (SELECT count(*) FROM status WHERE status_rating = 5 AND status_media_id = :id),
mediastats_rating_6 = (SELECT count(*) FROM status WHERE status_rating = 6 AND status_media_id = :id),
mediastats_rating_7 = (SELECT count(*) FROM status WHERE status_rating = 7 AND status_media_id = :id),
mediastats_rating_8 = (SELECT count(*) FROM status WHERE status_rating = 8 AND status_media_id = :id),
mediastats_rating_9 = (SELECT count(*) FROM status WHERE status_rating = 9 AND status_media_id = :id),
mediastats_rating_10 = (SELECT count(*) FROM status WHERE status_rating = 10 AND status_media_id = :id)
WHERE mediastats_media_id = :id
The :id is added from PHP.
Here's how I'd do it in PHP with PDO:
$sql = "
SELECT
COUNT(*) AS mediastats_members,
AVG(status_rating) AS mediastats_avscore,
SUM(status_status = 'done') AS mediastats_done,
SUM(status_status = 'doing') AS mediastats_doing,
SUM(status_status = 'redoing') AS mediastats_redoing,
SUM(status_status = 'dropped') AS mediastats_dropped,
SUM(status_status = 'wantto') AS mediastats_wantto,
SUM(status_status = 'wont') AS mediastats_wont,
SUM(status_status = 'stalled') AS mediastats_stalled,
SUM(status_rating = 1) AS mediastats_rating_1,
SUM(status_rating = 2) AS mediastats_rating_2,
SUM(status_rating = 3) AS mediastats_rating_3,
SUM(status_rating = 4) AS mediastats_rating_4,
SUM(status_rating = 5) AS mediastats_rating_5,
SUM(status_rating = 6) AS mediastats_rating_6,
SUM(status_rating = 7) AS mediastats_rating_7,
SUM(status_rating = 8) AS mediastats_rating_8,
SUM(status_rating = 9) AS mediastats_rating_9,
SUM(status_rating = 10) AS mediastats_rating_10
FROM status
WHERE status_media_id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(array("id"=>$id));
$params = $stmt->fetch(PDO::FETCH_ASSOC);
This way you calculate all the aggregates in one pass of the table, instead of using a separate subquery for each count.
I'm using a trick of MySQL -- the SUM() of a boolean expression is equal to the COUNT() where the expression is true. This is because MySQL boolean expressions always return 0 or 1, and the SUM of 0's and 1's is equal to the COUNT of the 1's.
Then you can use the result from the above query as the parameters array to an UPDATE statement:
$sql = "
UPDATE mediastats SET
mediastats_members = :mediastats_members,
mediastats_avscore = :mediastats_avscore,
mediastats_done = :mediastats_done,
mediastats_doing = :mediastats_doing,
mediastats_redoing = :mediastats_redoing,
mediastats_dropped = :mediastats_dropped,
mediastats_wantto = :mediastats_wantto,
mediastats_wont = :mediastats_wont,
mediastats_stalled = :mediastats_stalled,
mediastats_rating_1 = :mediastats_rating_1,
mediastats_rating_2 = :mediastats_rating_2,
mediastats_rating_3 = :mediastats_rating_3,
mediastats_rating_4 = :mediastats_rating_4,
mediastats_rating_5 = :mediastats_rating_5,
mediastats_rating_6 = :mediastats_rating_6,
mediastats_rating_7 = :mediastats_rating_7,
mediastats_rating_8 = :mediastats_rating_8,
mediastats_rating_9 = :mediastats_rating_9,
mediastats_rating_10 = :mediastats_rating_10
WHERE mediastats_media_id = :id";
$stmt = $pdo->prepare($sql);
$params["id"] = $id;
$stmt->execute($params);
Since PHP 5.3.4, PDO accepts parameter array keys without the leading :. You need the colon when you declare the parameter placeholder in your query, but you don't need it in the array of values you supply to execute().
UPDATE (
SELECT status_media_id,
COUNT(*) AS cnt, AVG(status_rating) AS avg_rating,
SUM(status_status = 'done') AS cnt_done,
...
FROM status
WHERE status_media_id = :id
) s
JOIN mediastats ms
ON ms.mediastats_media_id = s.status_media_id
SET ms.mediastats_members = cnt,
ms.mediastats_avscore = avg_rating,
ms.mediastats_done = cnt_done,
...