Sorry for my lack of knowledge in MySQL but how do you get the same value in different field?
For example if i have a table like so :
+-----+-----+-----+
| id | A | B |
+=====+=====+=====+
| 1 | 1 | 2 |
| 2 | 3 | 1 |
+-----+-----+-----+
And i would like to get the value 1 from A and B.
I tried doing something like :
SELECT A, B FROM table_name WHERE A = 1 AND B = 1
But this won't return a value if somehow A or B doesn't have the value 1. In cases like that I want it to only return the value 1 from the column that does have it. I want something like this :
SELECT A, B FROM table_name WHERE value = 1
I think you want OR:
SELECT A, B
FROM t
WHERE A = 1 OR B = 1
This can be shortened using IN:
WHERE 1 IN (A, B)
You should use query as:
SELECT A, B FROM table_name WHERE A = 1 OR B = 1
Here, you get rows which have either A=1 or B=1 or both A & B = 1.
Related
I have a table, the columns are like this:
| id | position | A | B | C | D | E |
I'm selecting by id. If the position is '1', it should return column A, B, C.
If not, it should return column D, E
For example, if the table is:
| id | position | A | B | C | D | E |
| 0 | 1 | a | b | c | d | e |
| 1 | 2 | a | b | c | d | e |
When the query selects id=0, the result should be:
| 0 | 1 | a | b | c |
When the query selects id=2, the result should be:
| 1 | 2 | d | e |
How should I write the SQL query?
you can't write a query to select columns according to selected rows.
but if you want specific columns you can try this:
SELECT id, position, A, B, C
FROM tablename
WHERE id = 1
Try this...
select id, position,
if (id=0, A, D),
if (id=0, B, E),
if (id=0, C, "")
from Table1
It's a little inflexible but it's a start. You can play with it here: http://sqlfiddle.com/#!9/d47c33/10/0
You cannot have a result set with a different number of columns per row, so it will have to be | 1 | 2 | d | e | NULL |.
To get what you want you can make two queries and UNION them together. Otherwise you could make a CASE statement for each column, but don’t do this if you don’t have to.
If you have any choice in the matter, I would recommend just making two queries and process the results separately.
But the UNION:
select id, position, a, b, c
from cool_table
where id in (1, 2, 3, 4, 5)
and position = 1
UNION
select id, position, d, e, null
from cool_table
where id in (1, 2, 3, 4, 5)
and position <> 1
Really though, this seems like you’re going “against the grain”. Perhaps some improvement can be made elsewhere that will make this unnecessary.
A database query is not the place to put display logic. As others have said, a query has a fixed number of fields.
You could use if or case to null fields depending on the position field but it would be simpler to select all the fields, send them to the front end, and let it sort of out how to show the results.
I have to write an SQL query for the following:
Input:
Id | Name
-- | ----
1 | A
2 | B
3 | C
Output:
Id | Name | IdType
-- | ---- | -----
1 | A | O
2 | B | E
3 | C | O
I can extract odd or even rows by putting where condition Id % 2 = 0. But I'm not sure how to put 'O' or 'E' in the new column.
Like this, using the IF() function:
SELECT Id, Name, IF(Id % 2 = 0, 'E', 'O') AS IdType FROM table_name;
You make use of CASE and print E when Id%2=0 and O if Id%2 is not equal to 0
SELECT Id,Name,
CASE WHEN (Id%2)=0 THEN 'E'
ELSE 'O' END AS IdType
FROM [YourTable]
Use this query If you want to update your table
UPDATE table_name SET IdType = CASE
WHEN mod (Id, 2) = 0 THEN 'E'
WHEN mod (Id, 2) <> 0 THEN 'O'
ELSE IdType
END
If you just want to print,then Robby Cornelissen had a perfect answer for you
I have a table like this
+----+-------+---------+
| id |order | name |
+----+-------+---------+
| 1 | 2 | John |
| 2 | 1 | William |
| 3 | 4 | Karl |
| 4 | 3 | Michael |
+----+-------+---------+
I want to Move Karl from the fourth place to the second so the order field of Karl will be set to 2, John 3 and Michael 4.
Is there a way to update the table with only one query?
You can try a conditional update:
UPDATE mytable
SET myfield = CASE other_field
WHEN 1 THEN 'value1'
WHEN 2 THEN 'value2'
WHEN 3 THEN 'value3'
END
WHERE id IN (1,2,3)
If you know that Karl is already in fourth, and you know that he's moving up, then this should do it:
UPDATE mytable
SET order = (order - 1) % 3 + 2
WHERE ORDER BETWEEN 2 AND 4
For a more reusable query, if someone is moving from position B to position A in the list (A < B), you would do this (substitute real numbers for A and B):
UPDATE mytable
SET order = (order - A + 1) % (B - A + 1) + A
WHERE ORDER BETWEEN A AND B
If you want to move someone down the list, from position A to B, instead, do this:
UPDATE mytable
SET order = (order - A - 1) % (B - A + 1) + A
WHERE ORDER BETWEEN A AND B
and everyone in between will be updated appropriately.
Thank you for your answers.
They help me come up with a single query that updates the order field from any position A to any position B:
UPDATE mytable
SET order=MOD(order-LEAST(A,B)+SIGN(A-B),GREATEST(A,B)-LEAST(A,B)+1)+LEAST(A,B)
WHERE order BETWEEN LEAST(A,B) AND GREATEST(A,B)
I'm trying to display the column name of the my table if it has the value 1
| A | B | C | D |
| 0 | 1 | 1 | 0 |
In this case i would like to get the result:
| Column |
| B |
| C |
I wrote the following query but it is not working:
SHOW COLUMNS
FROM `questions`
WHERE VALUES=`1`
If you just need a list of the columns that contain the value = 1, you should be able to use the following query:
select col
from
(
select col,
case s.col
when 'A' then A
when 'B' then B
when 'C' then C
when 'D' then D
end AS val
from yourtable
cross join
(
select 'A' AS col union all
select 'B' union all
select 'C' union all
select 'D'
) s
) s
where val = 1;
See SQL Fiddle with Demo. This uses a virtual table with your column names (A, B, etc) to unpivot your columns and then you just return only the column names that contain a value of 1. Credit for this technique goes to #Andriy M.
Say I have two tables a and b; the column id is unique in table a but has multiple entries in table b, with different values for column x as well as other columns in that table. The primary key of table b is (id,x).
I need to be able to join a single row from b to the SELECT query as I could do with MAX like so:
SELECT * FROM a
INNER JOIN b USING(id)
WHERE b.x = (SELECT MAX(x) FROM b WHERE b.id = a.id)
With MAX, this works no problem. But I don't need MAX. I actually need something like this:
SELECT * FROM a
INNER JOIN b USING(id)
WHERE b.x = (SELECT x FROM b
WHERE x IN (2,3,7) OR x IS NULL
ORDER BY FIELD(x,3,2,7) DESC
LIMIT 1)
This query fails because my MySQL version does not support LIMIT in this subquery. Is there another way to make sure to join at least and exactly one row in the order I provided?
Schematic overview of what I'm trying to do would be:
Select * from table a for each id
Join table b where x = 7
If no entry in b exists where a.id=b.id and x = 7, join b where x = 2
If no entry in b exists where a.id=b.id and x IN (2,7), join b where x = 3
If no entry in b exists where a.id=b.id and x IN (2,3,7), join b where x IS NULL
I have this need because:
I can't use more than one query in this particular bit of code I need; it has to be one magic all-in-one query
I can't use INNER JOIN (SELECT *) statements
I can't have a query where any id is present more than once (so DISTINCT is not option because the values in table b might differ)
I know for sure that table b has an entry for a.id where x is either 2, 3, 7 or NULL, but I don't know which and I also don't know how many entries there are for a.id in table b.
Upgrading MySQL is not the best option since this code would have to work on generic servers of any of my customers
So, in short, my question is: is there a function similar to MAX that can take a specific order into account instead of the MAX value?
Thanks in advance!
You can do this by specifying manually the ordering weight of each X.
mysql> select * from aa;
+----+------+
| id | name |
+----+------+
| 1 | John |
| 2 | Ted |
| 3 | Jill |
| 4 | Jack |
+----+------+
4 rows in set (0.00 sec)
mysql> select * from bb;
+------+------+------------+
| id | x | class |
+------+------+------------+
| 1 | 7 | HighPriori |
| 1 | 2 | MediumPrio |
| 1 | 3 | LowPriorit |
| 2 | 2 | Medium |
| 2 | 3 | Low |
| 3 | 3 | Low only |
+------+------+------------+
5 rows in set (0.00 sec)
select version();
+-------------+
| version() |
+-------------+
| 5.5.25a-log |
+-------------+
SELECT aa.name, bb.x, bb.class
FROM aa LEFT JOIN bb ON (aa.id = bb.id AND bb.x IN (2,3,7)
AND bb.x = ( SELECT x FROM bb WHERE bb.id = aa.id AND x IN (2,3,7)
ORDER BY CASE
WHEN x = 7 THEN 100
WHEN x = 2 THEN 200
WHEN x = 3 THEN 300
ELSE 400
END LIMIT 1 )
);
The innermost SELECT will choose the most suitable value of X based on priority: 7 if available, else 2, else 3. This works also if, as in this case, the "priorities" are not in order, i.e., 7 is higher than 3, but 2 is also higher than 3.
Then the LEFT JOIN will match that one record, if it exists, or NULL, if it does not.
John has 2,3 and 7 and gets the 7-record, while Ted has 2 and 3, and gets the 2:
+------+------+------------+
| name | x | class |
+------+------+------------+
| John | 7 | HighPriori |
| Ted | 2 | Medium |
| Jill | 3 | Low only |
| Jack | NULL | NULL |
+------+------+------------+
(Strictly speaking, the IN (2,3,7) in the inner SELECT and the ELSE in the CASE are redundant; either will do).
In CASE of need...
If the X field already establishes an order, e.g., you want the values 3,2,7 in either 2 - 3 - 7 or 7 - 3 - 2 numeric order, you can do without the CASE: instead of
ORDER BY CASE
WHEN x = 7 THEN 100
WHEN x = 2 THEN 200
WHEN x = 3 THEN 300
ELSE 400
END
you can just specify
ORDER BY x
or
ORDER BY x DESC
...the performance improvement is slight, even if x is indexed on, but if you have a great many values of X, then specifying them all in the CASE can be awkward, and studying exceptions may be lengthy.
But let's imagine you wanted the objects to be in this order
First Last
20,21,22,23,40,41,42,9,1,2,3,4,5
which typically arises when X is declared unsigned with values 1-5 ("we will never need more classes and 1 is always going to be first!"), then some weeks later someone adds a "this is a new exciting product, must go first!" exception and assigns 9 to it, and finally it happens again with "let's add a whole new XY class starting with 2X and 4X for the forthcoming product series...", you could do this as
WHEN x <= 5 THEN 900+x
WHEN x = 9 THEN 809
ELSE 700 + x
which translates the above jumbled set in the ordered sequence
720,721,722,723,740,741,742,809,901,902,903,904,905
and with three WHENs you do all the work.
SELECT * FROM a
INNER JOIN b USING(id)
WHERE b.x = (SELECT x FROM b
WHERE x IN (2,3,7) OR x IS NULL
ORDER BY FIELD(x,3,2,7) DESC
LIMIT 1)
switch the subquery to a join
SELECT * FROM a
join ( SELECT x FROM b
WHERE x,id IN (2,3,7) OR x IS NULL
ORDER BY FIELD(x,3,2,7) DESC
LIMIT 1) as X on X.id = a.id