I need to combined 2 tables with the same ids in it but i can't
SELECT stat.user_id, user.username,
SUM(stat.vertrag) AS vertrag,
SUM(stat.zubehoer) AS zubehoer,
SUM(stat.privat) AS privat,
SUM(stat.service) AS service,
SUM(stat.bs_vertrag) AS bus
FROM statistics stat
join users user on stat.user_id = user.uid
WHERE stat.user_id != '0' AND stat.datum LIKE '%$month%'
GROUP BY stat.user_id
UNION
SELECT bew.user_id, stat.user_id, user.username,
SUM(case when bew.log = 'inv_imei'
THEN
1
ELSE
0
END) AS inv
FROM user_bewegungen bew
JOIN users user ON user.uid = bew.user_id
JOIN statistics stat ON bew.user_id = stat.user_id
WHERE bew.date LIKE '%$month%'
GROUP BY bew.user_id
ORDER BY vertrag DESC
I am dont know how to go now.....
The first select is perfect, and works. now i have add a union because i need to add the row "log". Id's are also in it but i become the error
The used SELECT statements have a different number of columns
Can anyone help?
Each select statement needs to have the same number of columns. Your first one has 7:
SELECT
stat.user_id,
user.username,
SUM(stat.vertrag) AS vertrag,
SUM(stat.zubehoer) AS zubehoer,
SUM(stat.privat) AS privat,
SUM(stat.service) AS service,
SUM(stat.bs_vertrag) AS bus
Your second one has 4:
SELECT
bew.user_id,
stat.user_id,
user.username,
SUM(case when bew.log = 'inv_imei' THEN 1 ELSE 0 END) AS inv
You can select NULL in the second SELECT for those columns that aren't in the first one.
Make the two operands of the UNION isomorphic. Rename columns and/or create NULL-valued dummy columns as necessary to give them the same shape. FOR EXAMPLE, if we wanted to form the UNION of:
SELECT a, b, c
FROM table1
and:
SELECT d, e
FROM table2
we would logically pair those columns that are of the same types (in this case, let's assume that a and e are of the same type, and that b and d are of the same type) and add an extra NULL-valued column as the third projected attribute of the right-hand SELECT, as follows:
SELECT b, a, c
FROM table1
UNION
SELECT d AS b, e AS a, NULL as c
FROM table2
If such an approach seems confusing, you can use table views to simplify the expression. In the preceding example, you could have asserted a view atop table2:
CREATE VIEW t2view( b, a, c )
AS
SELECT d, e, NULL
FROM table2
and then formulated your UNION as:
SELECT b, a, c
FROM table1
UNION
SELECT *
FROM t2view
In UNION, the field numbers should be the same. Use like this:
SELECT stat.user_id, 0, user.username, ....
SELECT bew.user_id, stat.user_id, user.username, ...
or use something else, what you know, that is a missing field there.
The data types should be the same also.
You are using MySQL Union.
UNION is used to combine the result from multiple SELECT statements into a single result set.
The column names from the first SELECT statement are used as the column names for the results returned. Selected columns listed in corresponding positions of each SELECT statement should have the same data type. (For example, the first column selected by the first statement should have the same type as the first column selected by the other statements.)
Reference: MySQL Union
Your first select statement has 7 columns and second statement has 4.
You should have same number of column and also in same order in both statement.
otherwise it shows error or wrong data.
you can see this example
there are two queries both queries have the same number of columns.
column name can be different.
select 'row1' as column1,'row2' as column2
union
select 'row3' as column11,'row4' as column222
if you change columns count, it means in first query you are selecting 2 columns and in second query you are using 3 columns then it will through an error (The used SELECT statements have a different number of columns).
select 'row1' as column1,'row2' as column2
union
select 'row3' as column11,'row4' as column222 ,'rr' as t ;
run both queries you will see differnce.
Related
I am trying to make a request where I select from an array of value using the IN, but inside this array, if I have the same value twice, I'd like the request to return the result twice.
To clarify, here is an example:
select id_exo, count(id_exo) FROM BLOC WHERE id_seance IN (10,10) group by id_exo
So inside the IN, I put 2 times the value 10.
Here is the result:
id_exo
count(id_exo)
60
1
82
1
But in count, I'd like to have the number 2 since I have put twice 10 inside my IN.
How can I achieve that?
SELECT id_exo, COUNT(id_exo)
FROM bloc
JOIN (SELECT 10 id_seance
UNION ALL
SELECT 10) val USING (id_seance)
GROUP BY id_exo
Prior to MySQL 8.0 you can join with a sub select:
select * from BLOC as b
inner join (
select 1 as 'id', 10 as 'value'
union
select 2,10
union
select 3,10) as myValues on myValues.value = b.id_seance
You need the id column as the UNION statement removes duplicate rows
If you are lucky enough to have MySQL 8.0 look at the VALUES statement
https://dev.mysql.com/doc/refman/8.0/en/values.html
Here you should instead be able to join with something like
VALUES ROW(10), ROW(10), ROW(10)
In my query I use join table category_attributes. Let's assume we have such rows:
category_id|attribute_id
1|1
1|2
1|3
I want to have the query which suites the two following needs. I have a variable (php) of allowed attribute_id's. If the array is subset of attribute_id then category_id should be selected, if not - no results.
First case:
select * from category_attributes where (1,2,3,4) in category_attributes.attribute_id
should give no results.
Second case
select * from category_attributes where (1,2,3) in category_attributes.attribute_id
should give all three rows (see dummy rows at the beginning).
So I would like to have reverse side of what standard SQL in does.
Solution
Step 1: Group the data by the field you want to check.
Step 2: Left join the list of required values with the records obtained in the previous step.
Step 3: Now we have a list with required values and corresponding values from the table. The second column will be equal to required value if it exist in the table and NULL otherwise.
Count null values in the right column. If it is equal to 0, then it means table contains all the required values. In that case return all records from the table. Otherwise there must be at least one required value is missing in the table. So, return no records.
Sample
Table "Data":
Required values:
10, 20, 50
Query:
SELECT *
FROM Data
WHERE (SELECT Count(*)
FROM (SELECT D.value
FROM (SELECT 10 AS value
UNION
SELECT 20 AS value
UNION
SELECT 50 AS value) T
LEFT JOIN (SELECT value
FROM Data
GROUP BY value) D
ON ( T.value = D.value )) J
WHERE value IS NULL) = 0;
You can use group by and having:
select ca.category_id
from category_attributes ca
where ca.attribute_id in (1, 2, 3, 4)
group by ca.category_id
having count(*) = 4; -- "4" is the size of the list
This assumes that the table has no duplicates (which is typical for attribute mapping tables). If that is a possibility, use:
having count(distinct ca.attribute_id) = 4
You can aggregate attribute_id into array and compare two array from php.
SELECT category_id FROM
(select category_id, group_concat(attribute_id) as attributes from category_attributes
order by attribute_id) t WHERE t.attributes = (1, 2, 3);
But you need to find another way to compare arrays or make sure that array is always sorted.
I'm trying to show staff_code, staff_name and dept_name for those who have taken one book.
Here's my query:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME,BT.BOOK_CODE
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM,BOOK_TRANSACTIONS BT
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE = (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
It gives the error:
single-row subquery returns more than one row.
How to solve this?
Change = to IN:
WHERE SM.STAFF_CODE IN (SELECT ...)
Because the select returns multiple values, using equals won't work, but IN returns true if any of the values in a list match. The list can be a hard-coded CSV list, or a select with one column like your query is.
That will fix the error, but you also need to remove BOOK_TRANSACTIONS from the table list and remove BOOK_CODE from the select list.
After making these changes, your query would look like this:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE IN (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
I recommend learning the modern (now over 25 year old) JOIN syntax.
SELECT quantity, materialTypeId ,
(SELECT typeName
FROM invTypes
WHERE TypeID IN (SELECT materialTypeId
FROM invTypeMaterials
WHERE typeId= 12743
)
) AS material
FROM invTypeMaterials
WHERE TypeID=12743
so this query gives me nice results except the column material. only shows me the first entry instead of giving the name of each row.
if i run these sql seperate they work and i do see what i want. i just need them combined into 2 columns.
what i want to do is, i query one table for data, one of the column has a value wich i want to convert to a name, and that is in another table and its linked by a unique TypeID
Chilly
May be this will work :
SELECT tm.quantity, tm.materialTypeId , t.typeName
FROM invTypeMaterials tm
INNER JOIN invTypes t ON t.TypeID = tm.materialTypeId
WHERE tm.TypeID=12743
If you want to lookup the materialTypeID's name for the current record, you must not use a separate subquery but use the materialTypeID value from the outer query.
This is called a correlated subquery:
SELECT quantity, materialTypeId,
(SELECT typeName
FROM invTypes
WHERE TypeID = invTypeMaterials.materialTypeId
) AS material
FROM invTypeMaterials
WHERE TypeID=12743
I have a list of ids, and I want to query a mysql table for ids not present in the table.
e.g.
list_of_ids = [1,2,4]
mysql table
id
1
3
5
6
..
Query should return [2,4] because those are the ids not in the table
since we cant view ur code i can only work on asumption
Try this anyway
SELECT id FROM list_of_ids
WHERE id NOT IN (SELECT id
FROM table)
I hope this helps
There is a horrible text-based hack:
SELECT
substr(result,2,length(result)-2) AS notmatched
FROM (
SELECT
#set:=replace(#set,concat(',',id,','),',') AS result
FROM (
select #set:=concat(',',
'1,2,4' -- your list here
,',')
) AS setinit,
tablename --Your tablename here
) AS innerview
ORDER BY LENGTH(result)
LIMIT 1;
If you represent your ids as a derived table, then you can do this directly in SQL:
select list.val
from (select 1 as val union all
select 2 union all
select 4
) list left outer join
t
on t.id = list.val
where t.id is null;
SQL doesn't really have a "list" type, so your question is ambiguous. If you mean a comma separated string, then a text hack might work. If you mean a table, then something like this might work. If you are constructing the SQL statement, I would advise you to go down this route, because it should be more efficient.