How to show table row data as a column? - mysql

I have faced problem in selection data from database.
Main table:
TYPE DATE
APPLE 2013-10-02
BANANA 2013-2-4
KIWI 2014-10-2
I want to show
APPLE BANANA KIWI
2013-10-02 2013-2-4 2014-10-2
How can i do this ?

In Excel this function is called Transpose.
You have one good example and working code here:
https://dba.stackexchange.com/questions/47902/how-to-transpose-convert-rows-as-columns-in-mysql

Try this
SELECT CASE WHEN Type = 'APPLE' Then Date End APPLE,
CASE WHEN Type = 'BANANA' Then Date End BANANA,
CASE WHEN Type = 'KIWI' Then Date End KIWI,
From Table1

Related

mysql - how to clear some fields content that contains the specific value

I have a database in mysql. I want clear field contents that contains specific value.
I have database like this:
`id` `cat1` `cat2` `cat3`
1 1185 A1 3185
2 1585 A2 3131
3 2513 B3 3113
4 3369 C4 3333
I want to clear only 'fields' (not entire row) that contain "A" in cat2 column.
how should I do that?
my query doesn't seem to work properly.
instead delete entire row.
DELETE FROM table_name WHERE cat2='A*';
You can use UPDATE to update the value to NULL or an empty string instead of deleting the entire row/column. Use REGEXP to implement regex.
UPDATE EMPLOYEE SET cat2='' WHERE cat2 REGEXP '^A';
Use LIKE:
UPDATE table_name SET cat2 = NULL WHERE cat2 LIKE 'A%';
How about overwrite cat2 with a CASE expression? Verbose but you can clearly see what's going on.
SELECT id, cat1,
CASE
WHEN cat2 NOT LIKE 'A%' THEN cat2
END AS cat2
,cat3
FROM my_table;

SQL condition where 2 values share common character

I'm trying to create a query that lists staffID, staffName and staffDOB, but only of staff that first and last names begin with the same letter. So I have both staffFirst and staffLast as individual columns, will join them together. I will not be customising staffID and staffDOB. I would like it to return the name of staff like adam apple = a apple, so the output would look like:
staffID | staffName | staffDOB
------------------------------
1 | A Apple | 12/10/99
.... | .... | ....
All columns are in the same table "N_Staff". I am using HeidiSQL which I believe uses MySQL. I know how to grab the data of each column, though it is selecting the first letters of both first and last names and comparing them which is confusing me as it is not an specific letter I am looking for but any letter that is common on both tables of index [0].
Thus far:
SELECT staffID FROM N_Staff,
SELECT staffFirst, staffLast AS staffName
FROM N_Staff WHERE ... , --perhaps should be using LEFT ?
SELECT staffDOB from N_Staff;
How about:
SELECT staffID, CONCAT(LEFT(staffFirst,1), ' ', staffLast) AS staffName, staffDOB
FROM N_Staff
WHERE LEFT(staffFirst,1) = LEFT(staffLast,1)
use this:
SELECT * FROM NS_WORDS;
mani
nikhil
sugandh
mining
_lkdnsad
_lkdndsadnjas
_lk
_ja
_ls
_lsa
nikhil nikhil
nikhil name
SELECT * FROM NS_WORDS
where not( to_char(SUBSTR(a,1,1))=to_char(substr(a,instr(a,' ',1,1),1)));
output:
nikhil nikhil
nikhil name
your where will go like:
where not( to_char(SUBSTR(staffName ,1,1))=to_char(substr(staffName
,instr(staffName ,' ',1,1),1)));

SQL: How to replace an entire field if it matches a string?

I am trying to replace an entire field from a database when it matches a certain string.
For example:
TABLE_FRUITS contains
ID NAME
---------------
1 APPLE
2 ORANGE
3 PASSIONFRUIT
4 BANANA
5 DRAGONFRUIT
6 KIWI
7 STRAWBERRY FRUIT
Now If I try to select column NAME, and if a field contains the string 'FRUIT', it should replace that whole field to another string, like 'SAMPLE'.
Expected result:
select NAME from TABLE_FRUITS;
would return:
APPLE
ORANGE
SAMPLE
BANANA
SAMPLE
KIWI
SAMPLE
I am not sure if I should use replace or substr/instr.
If you're using MySQL, you could use something like
SELECT IF(NAME LIKE '%FRUIT%', 'SAMPLE', NAME) AS NAME FROM TABLE_FRUIT
In other varieties of SQL you will probably need to use a CASE expression:
SELECT CASE WHEN NAME LIKE '%FRUIT%' THEN 'SAMPLE' ELSE NAME END AS NAME FROM TABLE_FRUIT
Use case when:
select case when name like '%fruit%' then 'Sample' else name end from tablename
You can use CASE
select case when name like '%FRUIT%' then 'sample' else name end
from table_fruit

SQL merge results of different rows, combined by a case

i have the folowing table:
type | amount
pine | 10
cypress | 40
gold | 30
sylver | 25
I would like to classify, merge and sum within a case:
SELECT CASE WHEN (type == 'pine' OR type == 'cypress') then 'wood' end, from materials;
I would liek to get:
wood | 50
gold | 30
silver | 25
I though a case would merge the results but apparently isnt the case, i'm trying with a SUM but without success.
You can use the CASE statement like that, but you'll also have to group later to get the total values. Try this:
SELECT
(CASE WHEN type = 'pine' OR type = 'cypress' THEN 'wood' ELSE type END) AS type,
SUM(amount) AS total
FROM myTable
GROUP BY type;
Your case statement doesn't have any ELSE to it. You should include this, because it appears that if it's not pine or cypress, then you want to select whatever type already exists for that material.
Try this:
SELECT CASE WHEN (type == 'pine' OR type == 'cypress') then 'wood' end as MacroType, count(*) from materials group by MacroType;

Update a list of things without hitting every entry

I have a list in a database that the user should be able to order.
itemname| order value (int)
--------+---------------------
salad | 1
mango | 2
orange | 3
apples | 4
On load from the database, I simply order by order_value.
By drag 'n drop, he should be able to move apples so that it appears at the top of the list..
itemname| order value (int)
--------+---------------------
apples | 4
salad | 1
mango | 2
orange | 3
Ok. So now internally I have to update EVERY LIST ITEM! If the list has 20 or 100 items, that's a lot of updates for a simple drag operation.
itemname| order value (int)
--------+---------------------
apples | 1
salad | 2
mango | 3
orange | 4
I'd rather do it with only one update. One way I thought of is if "internal Order" is a double value.
itemname| order value (double)
--------+---------------------
salad | 1.0
mango | 2.0
orange | 3.0
apples | 4.0
SO after the drag n' drop operation, I assign apples has a value that is less than the item it is to appear in front of:
itemname| order value (double)
--------+---------------------
apples | 0.5
salad | 1.0
mango | 2.0
orange | 3.0
.. and if an item is dragged into the middle somewhere, its order_value is bigger than the one it appears after .. here I moved orange to be between salad and mango:
itemname| order value (double)
--------+---------------------
apples | 0.5
salad | 1.0
orange | 1.5
mango | 2.0
Any thoughts on better ways to do this?
Suppose #old is the value 4 for the old position of apples, and #new is the new position 1.
set #old = 4;
set #new = 1;
UPDATE Items
SET `order value` =
CASE `order value` WHEN #old THEN #new
ELSE `order value` + SIGN(#old-#new) END
WHERE `order value` BETWEEN LEAST(#old, #new) AND GREATEST(#old, #new);
I used MySQL 5.1.52 to test this on your example data and it works. The identical SQL also works if you need to move an early entry to be later, or move one in the middle, etc. Just set the values of #old and #new.
I ended up using an adjacencies table. I didn't know about it at the time.
I'm not sure if this counts as a solution, but you don't literally need to do one update for every row. If you move 'foo' from position 4 to position 1, you just do
UPDATE table SET position = 1 WHERE itemname = 'foo'
UPDATE table SET position = position + 1 WHERE itemname != 'foo' AND position < 4
It's the same number of updates even if you're moving from position 1000 to 500, or from 500 to 1000 (although you'll need to flip it, naturally), you just need to mass shift all the affected rows plus or minus one
You can do it in a single Update statement like so:
Update Table
Set OrderValue = Case
When Table.ItemName = 'apples' Then 0
Else (
Select Count(*)
From Table As T1
Where T1.ItemName <> 'apples'
And T1.OrderValue < Table.OrderValue
) + 1
End + 1
You would obviously replace apples with the selected value. However, I would think that this type of sorting would best done in the client application rather than in the database.
If you were using SQL Server uou could do this using a linked-list representation and CTEs. I don't know whether mysql supports CTEs though...
SET NOCOUNT ON
GO
DROP TABLE [Item]
GO
CREATE TABLE [Item]
(
[ItemId] int NOT NULL PRIMARY KEY,
[Name] varchar(100) NOT NULL,
[PreviousId] int NULL
)
GO
INSERT [Item] VALUES (6, 'apples', 3)
INSERT [Item] VALUES (3, 'orange', 36)
INSERT [Item] VALUES (9, 'mango', 100)
INSERT [Item] VALUES (100, 'salad', NULL)
INSERT [Item] VALUES (36, 'banana', 9)
GO
;WITH
[LinkedItem] AS
(
SELECT
[Item].*,
1 AS [OrderValue]
FROM [Item]
WHERE [Item].[PreviousId] IS NULL
UNION ALL
SELECT
[Item].*,
[LinkedItem].[OrderValue] + 1
FROM [Item]
INNER JOIN [LinkedItem] ON [LinkedItem].[ItemId] = [Item].[PreviousId]
)
SELECT *
FROM [LinkedItem]
ORDER BY
[LinkedItem].[OrderValue]
-- Drag orange up two spaces
DECLARE #MovingItemId int
DECLARE #NewPreviousId int
SET #MovingItemId = 3
SET #NewPreviousId = 100
DECLARE #OldPreviousId int
SELECT #OldPreviousId = [PreviousId] FROM [Item] WHERE [ItemId] = #MovingItemId
UPDATE [Item] SET [PreviousId] = #OldPreviousId WHERE [PreviousId] = #MovingItemId
UPDATE [Item] SET [PreviousId] = #MovingItemId WHERE [PreviousId] = #NewPreviousId
UPDATE [Item] SET [PreviousId] = #NewPreviousId WHERE [ItemId] = #MovingItemId
This produces the following before and after results:
100 salad NULL 1
9 mango 100 2
36 banana 9 3
3 orange 36 4
6 apples 3 5
100 salad NULL 1
3 orange 100 2
9 mango 3 3
36 banana 9 4
6 apples 36 5
I suppose you have a primary key on your table, an id column.
These two statements should do.
update table set order_value=0 where itemname='apples';
update
(select #num := 0 )vars
straight_join
(select id, #num := #num+1 as ord_value
from table
order by order_value
)big
inner join table t on t.id = big.id
set t.order_value = big.ord_value;
If you don't have an id, use itemname instead.
As has been suggested previously, and unless you have to show to all the users the current order that a given user is affecting, I would suggest that you treat this in the client first (there are many ways of solving this), and then, based on a user action (pressing the "I am done" button, for example) you update the rows in the database with the final order from the structure that you have chosen to store in the client.
You can make the code in the client as complex as you want to try to minimize the number of rows that need to be updated in the database: in some case, you may only need to insert one row (if the user inserts a new item at the end of the list); in many cases you may need to update two rows (if the user just swaps two consecutive items). The worst scenario as per the number of rows that need to be updated, is all the rows (you can device an algorithm that will only detect the rows that need to be updated and just update those). The choice is yours whether it is worth doing this or just issuing an update of all the rows.
The bottom line is that you do not need to update all the rows in the database, that situation is just one of the many possible scenarios. Some databases allow update in bulk (the name may vary from one database to another) and this will not be very expensive.
If the column simply specifes the order of the rows, I don't see anything wrong with using 0 and negatives.