Does COALESCE work properly with VIEWs? - mysql

I have my view definition:
CREATE VIEW `view` AS
SELECT a.id,
COALESCE(COALESCE(b.name, c.name), a.name) AS name
FROM a_table a
LEFT JOIN b_table b on a.b_id = b.id
LEFT JOIN c_table c on a.c_id = c.id
And after I'm updating a_table row with new name it doesn't get updated in my view. But if I change name to COALESCE(a.name, COALESCE(b.name, c.name)) AS name it works.
As I understand the reason is in COALESCE. It takes the first not null value and in my case it's b.name and gets updated only when b.name is updated.
Is there any option to updated the view when any of COALESCE values are changed?

COALESCE() works fine in views. It also takes multiple arguments, so I would suggest writing this as:
CREATE VIEW `view` AS
SELECT a.id, COALESCE(b.name, c.name, a.name) AS name
FROM a_table a LEFT JOIN
b_table b
ON a.b_id = b.id LEFT JOIN
c_table c
ON a.c_id = c.id;
Views are not "updated". They are SQL code that is plugged into queries when the view is reference. The data comes from the underlying tables.

Related

How to use GROUP_CONCAT on multiple JOIN

I am currently retrieving data from multiple tables using a cus_id as the initial query. From here I have multiple tables that can have various rows of data that I would like to retrieve and use GROUP_CONCAT to return this data in a single row. At the moment, my query is returning duplicate data based on the max number of rows returned by one of the group concats.
SELECT a.id,c.x,c.y,c.z
GROUP_CONCAT(a.column_a) AS aca,
GROUP_CONCAT(a.column_b) AS acb,
GROUP_CONCAT(b.column_a) AS bca,
GROUP_CONCAT(b.column_b) AS bcb,
FROM `table_a` a
INNER JOIN `table_b` b ON a.id = b.id
INNER JOIN `table_c` c ON a.id = c.id
WHERE a.id = ?
Also, in this scenario, what is the correct join method to use. I am expecting all the fields I am requesting to have some sort of data.
Problem was resolved by using sub queries to isolate the GROUP_CONCAT requests. This allowed me to get only the data I wanted without duplicate results manipulated by other JOIN requests.
SELECT a.id,c.x,c.y,c.z
(SELECT GROUP_CONCAT(column_a) FROM table_a) AS aca,
(SELECT GROUP_CONCAT(column_b) FROM table_a) AS acb,
(SELECT GROUP_CONCAT(column_a) FROM table_b) AS bca,
(SELECT GROUP_CONCAT(column_b) FROM table_b) AS bcb,
FROM table_a a
INNER JOIN `table_c` c ON a.id = c.id
WHERE a.id = ?
Aggregate before joining. Somthing along the lines of:
select
a.*,
b.grp_a,
b.grp_b,
c.grp_x,
b.grp_y
from table_a a
join
(
select
a_id,
group_concat(a order by b_id) as grp_a,
group_concat(b order by b_id) as grp_b
from table_b
group by a_id
) b on b.a_id = a.id
join
(
select
a_id,
group_concat(x order by c_id) as grp_x,
group_concat(y order by c_id) as grp_y
from table_c
group by a_id
) c on c.a_id = a.a_id
order by a.a_id;

mysql join and insert statement

I created a view using left join to see the number of duplicate ip.
In this view
SELECT
a.id,
b.id,
COUNT (b.id),
a.ip
FROM
`VIEW` AS a
LEFT JOIN
`VIEW` AS b on a.ip = b.ip
WHERE
a.id = 298
GROUP BY
b.id;
When i execute this query, i get the data i want for one id.
However, if i check the number of duplicate ip's in the whole id
and execute the following query to store it in the table.
INSERT
INTO
TABLE
SELECT
a.id,
b.id,
COUNT (b.id),
a.ip
FROM
`VIEW` AS a
LEFT JOIN
`VIEW` AS a.ip = b.ip
WHERE
a.id IN
(
SELECT DISTINCT
id
FROM
`VIEW`)
GROUP BY
b.id;
Other values come out.
The first query statement works fine and the second query statement shows an invalid value.
How can I use the second query statement to get the result of the first query statement?
Use GROUP BY a.id, b.id so that you get a separate count for each a.id that you join with.
There's also no reason to use LEFT JOIN here. Since you're joining the view with itself, there will always be a matching row. Just use a normal INNER JOIN.
The WHERE clause is totally ineffective. How can the id not be in the list of distinct id's from the same view? Get rid of that clause.
You also have a syntax error:
JOIN `VIEW` AS a.ip = b.ip
should be:
JOIN `VIEW` AS b ON a.ip = b.ip
The correct query should be:
INSERT
INTO
TABLE
SELECT
a.id,
b.id,
COUNT(*),
a.ip
FROM
`VIEW` AS a
JOIN
`VIEW` AS b ON a.ip = b.ip
GROUP BY
a.id, b.id;

mysql display field values from subquery

I have following query that works correctly:
select * from myTable a where a.company is null and exists (select b.company from myTable b where b.id = a.id and b.office_id = a.office_id and b.company is not null);
Now, I also want to display the field value b.company from the subquery next to the fields from myTable a.
How do I get this done?
Thank you and best regards
If you want results from multiple tables you should join the tables together.
Since you want only records from A that exist in B, you need to use an outer JOIN returning all records from A and only those matching in B. But then you want to exclude all those records from A that were not found in B.
SELECT *, b.company
FROM myTable a
LEFT JOIN myTable B
ON b.id = a.id
and b.office_id = a.office_id
and b.company_ID is not null
WHERE a.company is null
and B.ID is not null and B.office_ID is not null --this handles the exists part.

MYSQL getting the difference of two results

ok so my problem is that I have a set of results:
ID CODE
1 A
1 B
3 C
I also have another table of:
CODE
A
B
C
What I want to get using SQL is a query of CODES that each result from table 1 is missing. So basically:
ID CODE
1 C
3 A
3 B
Any help would be great.
You can use:
SELECT a.id, b.code
FROM (SELECT DISTINCT id FROM idcodes) a
CROSS JOIN codes b
LEFT JOIN idcodes c ON a.id = c.id AND b.code = c.code
WHERE c.id IS NULL
ORDER BY a.id, b.code
If you have another table that stores unique entries for id, it would be better to just use that table instead rather than a DISTINCT subselect:
SELECT a.id, b.code
FROM ids a
CROSS JOIN codes b
LEFT JOIN idcodes c ON a.id = c.id AND b.code = c.code
WHERE c.id IS NULL
ORDER BY a.id, b.code
SQLFiddle Demo
You can use exists. Construct the full list of possible variations with a Cartesian join and then ensure what you have isn't in this list.
select id, code
from idcode_table x
where not exists ( select 1
from idcode_table a
cross join code_table b
where b.code = x.code
and a.id = x.id )
This can also be re-written with a not in.
select id, code
from idcode_table
where (id, code) not in ( select distinct a.id, b.code
from idcode_table a
cross join code_table b )
The distinct is optional. It will make it slower to construct the list of possibles but quicker to determine if you have one of them already. I'd test it to see which is quicker.

Left Joins not Working with Subquery

I am trying to write this SQL:
SELECT
a.a_id as aid,
b.b_id as bid ,
c.title
FROM b ,
( SELECT
a.a_id
FROM a
WHERE a.type = '2'
) AS a
LEFT JOIN c ON b.b_id = c.c_id
If I don't put a reference to the LEFT JOIN or the select c, then it works. If I do put the left join, then I get an error that the b.b_id is an unknown column. Why can't I use a left join here or more specifically, why is any column in table b unknown? The first part of the statement is a normal select from table b, so why can't it find those columns?
When do you use subqueries versus inner joins? In this example:
Table a contains fixed length flags (a bunch of integers) with information about topics
Table c contains things like topic title, etc.
Table b contains the category information.
What I am trying to accomplish is to pull all categories of a certain type (table a), and also pull all topic titles (table c) where the category id is the same as what it is defined for the topic id (table b).
If you interchange table "a" with "b" the sql compiles (but does this give the results you seek?):
SELECT
a.a_id as aid,
b.b_id as bid,
c.title
FROM
( SELECT
a.a_id
FROM a
WHERE a.type = '2'
) AS a, b
LEFT JOIN c ON b.b_id = c.c_id
Try this
SELECT
a.a_id as aid,
b.b_id as bid ,
c.title
FROM b INNER JOIN
( SELECT
a.a_id
FROM a
WHERE a.type = '2'
) AS a
LEFT JOIN c ON b.b_id = c.c_id