How can I read more than one column in this - mysql

In 1_products t2 I have other columns called make,model
When I add them
(SELECT
t2.code,t2.make,t2.model
FROM .....
I get
Error 1241 Operand should contain 1 column(s)
SELECT
t1.fk_products_id,
(SELECT
t2.code
FROM
1_products t2
WHERE
t2.id = t1.fk_products_id
order by code
limit 1)
FROM
1_stock t1
WHERE
t1.branch = 1 and t1.dispatch <> 0;

You cannot return more than one column in an inline query. If you want to return more than one column for each t1.fk_products_id then you will have to rewrite the query similar to this:
SELECT t1.fk_products_id,
t2.code,
t2.make,
t2.model
FROM 1_stock t1
LEFT JOIN 1_products t2
on t1.fk_products_id = t2.id
WHERE t1.branch = 1
and t1.dispatch <> 0;

Related

Getting error "Operand should contain 1 column(s)" on this query

So I have the code below:
SELECT student_name FROM student S WHERE S.student_id IN
(SELECT t1.student_id, SUM(IF(t2.test_date IS NULL, 0, 1)) AS increase_score
FROM
test t1
LEFT JOIN test t2
ON t1.student_id = t2.student_id
AND t1.test_date < t2.test_date
AND t1.Score <= t2.Score
GROUP BY t1.student_id
HAVING
increase_score = 0
AND count(*) > 1)
I am getting an error "Operand should contain 1 column(s)". This only arises after adding the outer SELECT statement. I have confirmed the inner query is working as intended otherwise. I've looked at some other examples involving the same error, but I have not been able to determine what to do to fix it in this case.
The error is quite clear : you can't have more than one field in your sub query, you're macthing a field against a single column, obviously.
So just move the SUM in the HAVING clause :
SELECT student_name
FROM student S
WHERE S.student_id IN
(SELECT t1.student_id
FROM test t1
LEFT JOIN test t2
ON t1.Name = t2.Name
AND t1.Date < t2.Date
AND t1.Score <= t2.Score
GROUP BY t1.Name
HAVING
SUM(IF(t2.test_date IS NULL, 0, 1)) = 0
AND count(*) > 1)
http://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
A query used as an argument to the in operator must return a single column. One way to rework this query is to remove the sum in the select list, and keep it only in the having clause:
SELECT student_name
FROM student
WHERE student_id IN (SELECT t1.student_id
FROM test t1
LEFT JOIN test t2 ON t1.Name = t2.Name AND
t1.Date < t2.Date AND
t1.Score <= t2.Score
GROUP BY t1.Name
HAVING SUM(IF(t2.test_date IS NULL, 0, 1)) = 0 AND
COUNT(*) > 1
)

How do I make aggregate query return empty set instead of NULL row?

I have a SQL query like this:
SELECT t1.name, MAX(t2.value)
FROM t2
JOIN t1 ON t1.id = t2.t1_id
WHERE t2.t1_id = 1 AND t2.text_id = 16;
However, when t2 selection is empty, it returns a row containing NULL values (because of MAX function returning NULL when called on an empty set). I would like it to return an empty set instead. How can I achieve it?
Having clause fits perfectly here:
SELECT
t1.name, MAX(t2.value)
FROM
t2 JOIN t1 ON t1.id = t2.t1_id
WHERE
t2.t1_id = 1 AND t2.text_id = 16
-- GROUP BY something?
HAVING
MAX(t2.value) IS NOT NULL
Try this in sql server ...
with cte as
(
SELECT t1.name, MAX(t2.value) a
FROM t2
JOIN t1 ON t1.id = t2.t1_id
WHERE t2.t1_id = 1 AND t2.text_id = 16;
)
select * from cte where a is not null
try this in Mysql
select p.* from
(
SELECT t1.name, MAX(t2.value) a
FROM t2
JOIN t1 ON t1.id = t2.t1_id
WHERE t2.t1_id = 1 AND t2.text_id = 16;
) p where p.a is not null
Simply RETURN when you don't want to get a resultset.
IF ((SELECT MAX(t2.Value) FROM t2) > 0)
SELECT t1.name, MAX(t2.value)
FROM t2
JOIN t1 ON t1.id = t2.t1_id
WHERE t2.t1_id = 1 AND t2.text_id = 16
ELSE
RETURN
Totally agree with comment by Gordon Linoff.
To wrap select query in another select query is good idea but when we have many aggregate fields then it will become cumbersome to do and think about that you have to make change like this to more than 10 queries.
You should use GROUP BY clause to query which will help you to fix your mentioned issue but more than that it will help you to get aggregate values(field wise) based on group by clause. In your case you should use GROUP BY t1.name can work.
So your aggregate result set will be group by name.
If you do not use GROUP BY then think that you have name field which have 100 unique values but you'll only 1 row which all rows aggregated data which may be wrong implementation.
Here's some more details about aggregate functions and group by.

SQL Select where NOT matching specific selection

I have been using the following SQL:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event
WHERE t2.Event IS NULL
To select all rows from table 1 where table 2 is Null. This effectively filters out all my Table 1 data where Table 2 has data. However, I want to apply this only when a column in table 2 equals a certain value. Therefore I am looking to do a SELECT * FROM t2 WHERE t2.ID = 1 but am unsure how this fits into this query.
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event and t2.certain_column = 1234
WHERE t2.Event IS NULL
Also you can try query with NOT EXISTS:
SELECT DISTINCT NAME
FROM Events t1
WHERE NOT EXISTS(SELECT * FROM UserHistory t2
WHERE t1.Name = t2.Event AND t2.ID = 1)
You need to add the predicate to the JOIN condition:
SELECT DISTINCT NAME
FROM Events t1
LEFT JOIN UserHistory t2 ON t1.Name = t2.Event AND t2.ID = 1
WHERE t2.Event IS NULL;
If you add it to the WHERE you effectively turn your outer join into an inner join, meaning no rows will be returned (since NULL = 1 evaluates to false)

simple mysql query count fails

SELECT
count(t1.id) AS c1
FROM
table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c1 = 6 -> CORRECT!
SELECT
count(t2.id) AS c2
FROM
table2
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c2 = 1 -> CORRECT!
SELECT
count(t1.id) AS c1,
count(t2.id) AS c2
FROM
table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE
table2.mode = 'ls'
GROUP BY
t1.id
c1 = 6 -> CORRECT!
c2 = 6 -> WRONG!
How do I request both counts in one query, without getting wrong results?
I need to count two different requests at the same table (table1).
so, I'm using an alias for both request. (t1). Each alias-request is working fine alone. If I use both in the same query, i got wrong results.
count() will get you the number of records that are returned by your query. Since if you removed the counts and replaced it with * you would have 6 rows both of those counts are giving you 6.
Is there any reason why you cant use two sub selects and return the result of each of those?
So:
SELECT subQ1.c1, subQ2.c2 FROM
(SELECT count(t1.id) AS c1 FROM table2
LEFT JOIN table1 AS t1 ON (t1.uid = table2.uid)
WHERE table2.mode = 'ls') as subQ1,
(SELECT count(t2.id) AS c2 FROM table2
LEFT JOIN table1 AS t2 ON (t2.pid = table2.id)
WHERE table2.mode = 'ls') as SubQ2;
I believe your problem on the full query is your group by function. You are grouping by t.id, thus a1.id will have a different count based on how many rows you have.
What I mean by this is if there are 6 rows in table t, then count is going to return 6 for table t; but also since there looks to be a 1 to 1 relation on table a, there are 6 matching rows in table a to the 6 matching rows in table t. such that
t.id = a.id
1 = 1
2= 2 ...etc.
Thus your count is returning rows versus the count you believe you should have? I believe sum function is what you want to use here.
You could try this...but I'm not really sure what you're trying to do.
SELECT (...)
count(CASE WHEN t1.uid = t3.uid THEN t1.id ELSE NULL END) AS CBanz,
count(CASE WHEN ta1.pid = t3.id THEN a1.id ELSE NULL END) AS CBanz1
FROM
t0
LEFT JOIN (...)
LEFT JOIN t1 ON (t1.uid = t3.uid)
LEFT JOIN t1 AS a1 ON (a1.pid = t3.id)
WHERE (...)

sql query question

I have tables
table 1
id text
1 A
1 B
2 C
table 2
id text
1 x
1 f
2 y
2 z
I want to join them this way
1 A x
1 B f
2 C y
2 z
In other words i want to see all texts from table1 and table2 grouped by id, with no repeats.
Any ideas?
Update: as they say in comments, the logic is not clear, I'll try to explain.
I have current values in table_1 and deleted values in table_2.
Customer wants to see current values and deleted values in one table grouped by some id.
Simple solution to get something close to what you're looking for
SELECT t1.id, t1.text, t2.text
FROM tbl_1 t1
INNER JOIN tbl_2 t2
ON t1.id = t2.id
this will create output
1 A x
1 B x
2 C y
2 C z
Only different is now that the duplicated texts x and C should somehow removed.
Update
precondition: duplicates per id are either in tbl_1 or tbl_2 not both !
Joining a grouped select in addition to above simple solution will allow to create kind of "CASE-Filters" to get your desired output.
SELECT
t1.id,
CASE
WHEN t2.text = txt_i2 THEN t1.text
END AS txt_t1,
CASE
WHEN t1.text = txt_i1 THEN t2.text
END AS txt_t2
FROM (
SELECT
i1.id,
i1.text AS txt_i1,
i2.text AS txt_i2
FROM tbl_1 i1
INNER JOIN tbl_2 i2
ON i1.id = i2.id
GROUP BY id
) i
INNER JOIN tbl_1 t1
ON i.id = t1.id
INNER JOIN tbl_2 t2
ON t1.id = t2.id
You should create a view of the tbl_1-tbl_2-join to get more readable SQL:
CREATE OR REPLACE VIEW V_tbl_1_2 AS (
SELECT
t1.id,
t1.text AS txt_1,
t2.text AS txt_2
FROM tbl_1 t1
INNER JOIN tbl_2 t2
ON t1.id = t2.id
)
;
SELECT
t.id,
CASE
WHEN t.txt_2 = i.txt_2 THEN t.txt_1
END AS txt_t1,
CASE
WHEN t.txt_1 = i.txt_1 THEN t.txt_2
END AS txt_t2
FROM V_tbl_1_2 t
INNER JOIN (
SELECT *
FROM V_tbl_1_2
GROUP BY id
) i ON t.id = i.id
;
USE MYSQL VIEW OR JOIN
This works if you can have no more than two items per id in either table and if neither one has complete duplicates. (And I must also add that this can only work if MySQL is able to swallow this monster and not choke with it.)
SELECT
COALESCE (t1.id, t2.id) AS id,
t1.text AS text1,
t2.text AS text2
FROM (
SELECT
t.id,
t.text,
CASE t.text WHEN m.text THEN 1 ELSE 2 END AS rowid
FROM table_1 t
INNER JOIN (
SELECT id, MIN(text) AS text
FROM table_1
GROUP BY id
) m ON t.id = m.id
) t1
FULL JOIN (
SELECT
t.id,
t.text,
CASE t.text WHEN m.text THEN 1 ELSE 2 END AS rowid
FROM table_2 t
INNER JOIN (
SELECT id, MIN(text) AS text
FROM table_2
GROUP BY id
) m ON t.id = m.id
) t2
ON t1.id = t2.id AND t1.rowid = t2.rowid
ORDER BY COALESCE (t1.id, t2.id), COALESCE (t1.rowid, t2.rowid)