Display one column data to two column - mysql

Table A
| SLNO | TYPENAME | TYPEMODE |
------------------------------
| 1 | Act.Alw | A |
| 2 | Canteen | D |
I want to display two column according to its typmode
using UNION ALL I get
| Addition | Deduction |
------------------------
| Act.Alw | |
| | Canteen |
I want display like this. Addtion and Deduction are alias
| ADDITION | DEDUCTION |
------------------------
| Act.Alw | Canteen |

It looks like you need to use a join instead of a union. But it would be helpful if you could explain a little bit more about what you are trying to accomplish and maybe post he sql query you are currently trying to run.

You can use CASE statement for that. To group them you need to use GROUP_CONCAT function like this:
SELECT GROUP_CONCAT(CASE WHEN typemode = 'A'
THEN typename ELSE NULL END) AS Addition
,GROUP_CONCAT(CASE WHEN typemode = 'D'
THEN typename ELSE NULL END) AS Deduction
FROM Table1
Output:
| ADDITION | DEDUCTION |
------------------------
| Act.Alw | Canteen |
See this SQLFiddle

Related

Mysql count from multiple columns?

I have the following simplified tables:
statistics
+-------------+-------------+---------------+
| type | itemnumber | borrowernumber |
+-------------+-------------+---------------+
| issue | 26191 | 11978 |
+-------------+-------------+---------------+
| issue | 26190 | 11979 |
+-------------+-------------+---------------+
items:
+-------------+-------------+
| itemnumber | bibliono |
+-------------+-------------+
| 26191 | 27 |
+-------------+-------------+
| 26190 | 28 |
+-------------+-------------+
biblio_metadata:
+-------------+----------------------------------------------------+
| bibliono | metadata |
+-------------+----------------------------------------------------+
| 27 | <?xml.. <datafield tag="082" ind1="0" ind2="4"> |
| <subfield code="a">005.133/M29</subfield> |
| </datafield> |
+-------------+----------------------------------------------------+
| 28 | <?xml.. <datafield tag="082" ind1="0" ind2="4"> |
| <subfield code="a">995.133/M29</subfield> |
| </datafield> |
+-------------+----------------------------------------------------+
borrowers
+-------------+-------------+
| borrowerno | sort1 |
+-------------+-------------+
| 11978 | CAS |
+-------------+-------------+
| 11979 | CBA |
+-------------+-------------+
I want to get the following through a mysql query:
+-------------+------------+
| DDC Range | CAS | CBA |
+-------------+------------
| 001-100 | 1 | |
+-------------+------------
| 900-999 | | 1 |
+-------------+-----------+
I'm trying to find the right combination of queries - if it's mysql select query multiple columns or any other keyword but can't seem to get the right term to search.
I have the following made up mysql queries but can't go pass the first column 'CAS' and further query the other sort1's (in this example CBA).
SELECT CASE
WHEN ExtractValue(metadata, '//datafield[#tag="082"]/subfield[#code="a"]') REGEXP '^[0]{1}[0-9]{2}[^0-9]+.*' THEN "000-099"
WHEN ExtractValue(metadata, '//datafield[#tag="082"]/subfield[#code="a"]') REGEXP '^[9]{1}[0-9]{2}[^0-9]+.*' THEN "900-999"
ELSE "Others"
END as "DDC Range", count(borrowers.sort1)
from statistics s
LEFT JOIN items on (s.itemnumber=items.itemnumber)
LEFT JOIN biblio_metadata ON (items.biblionumber=biblio_metadata.biblionumber)
LEFT JOIN borrowers on (s.borrowernumber=borrowers.borrowernumber)
WHERE s.type = "issue"
AND borrowers.sort1="CAS"
GROUP BY Subjects
I'm looking into this COUNT(*) from multiple tables in MySQL but I don't know where to put the next query or if what I'm trying to arrive at is related to the aforementioned link. Thanks in advance
Looks like in your query you're filtering out all entries where borrowers.sort1="CAS" but if I understand correctly you'll need these.
Can't you just do all the joins as specified in your question and then use two case statements? As it seems you're interested in the count(*) per subject you can then sum them.
Maybe try something like below:
SELECT
CASE
WHEN ExtractValue(metadata, '//datafield[#tag="082"]/subfield[#code="a"]') REGEXP '^[0]{1}[0-9]{2}[^0-9]+.*' THEN "000-099"
WHEN ExtractValue(metadata, '//datafield[#tag="082"]/subfield[#code="a"]') REGEXP '^[9]{1}[0-9]{2}[^0-9]+.*' THEN "900-999"
ELSE "Others"
END as "DDC Range", count(borrowers.sort1),
sum(case when borrowers.sort1="CAS" then 1 else '' end) as 'CAS',
sum(case when borrowers.sort1="CBA" then 1 else '' end) as 'CBA'
from statistics s
LEFT JOIN items on (s.itemnumber=items.itemnumber)
LEFT JOIN biblio_metadata ON (items.biblionumber=biblio_metadata.biblionumber)
LEFT JOIN borrowers on (s.borrowernumber=borrowers.borrowernumber)
WHERE s.type = "issue"
GROUP BY Subjects

Select value from table sorted by a certain order from another table

I want to select value from table sorted by a certain order.
I have a table called test that looks like this:
| date | code | value |
+----------+-----------+----------+
| 20050104 | 000005.SZ | -6359.19 |
| 20050104 | 600601.SH | -7876.34 |
| 20050104 | 600602.SH | -25693.3 |
| 20050104 | 600651.SH | NULL |
| 20050104 | 600652.SH | -15309.9 |
...
| 20050105 | 000005.SZ | -4276.28 |
| 20050105 | 600601.SH | -3214.56 |
...
| 20170405 | 000005.SZ | 23978.13 |
| 20170405 | 600601.SH | 32212.54 |
Right now I want to select only one date, say date = 20050104, and then sort the data by a certain order (the order that each stock was listed in the stock market).
I have another table called stock_code which stores the correct order:
+---------+-----------+
| code_id | code |
+---------+-----------+
| 1 | 000002.SZ |
| 2 | 000004.SZ |
| 3 | 600656.SH |
| 4 | 600651.SH |
| 5 | 600652.SH |
| 6 | 600653.SH |
| 7 | 600654.SH |
| 8 | 600602.SH |
| 9 | 600601.SH |
| 10 | 000005.SZ |
...
I want to sorted the selected data by stock_code(code_id), but I don't want to use join because it takes too much time. Any thoughts?
I tried to use field but it gives me an error, please tell me how to correct it or give me an even better idea.
select * from test
where date = 20050104 and code in (select code from stock_code order by code)
order by field(code, (select code from stock_code order by code));
Error Code: 1242. Subquery returns more than 1 row
You told us that you don't want to join because it takes too much time, but the following join query is probably the best option here:
SELECT t.*
FROM test t
INNER JOIN stock_code sc
ON t.code = sc.code
WHERE t.date = '20050104'
ORDER BY sc.code_id
If this really runs slowly, then you should check to make sure you have indices setup on the appropriate columns. In this case, indices on the code columns from both tables as well as an index on test.date should be very helpful.
ALTER TABLE test ADD INDEX code_idx (code)
ALTER TABLE test ADD INDEX date_idx (date)
ALTER TABLE code ADD INDEX code_idx (code)

Pivot SQL data - groups rows into columns

I have data stored in a mySQL database in the following format:
+------------+------------+-----------+
| id | field | value |
+============+============+===========+
| 1 | first | Bob |
+------------+------------+-----------+
| 1 | last | Smith |
+------------+------------+-----------+
| 2 | first | Jim |
+------------+------------+-----------+
| 2 | last | Jones |
+------------+------------+-----------+
and I would like it returned as follows:
+------------+------------+-----------+
| id | first | last |
+============+============+===========+
| 1 | Bob | Smith |
+------------+------------+-----------+
| 2 | Jim | Jones |
+------------+------------+-----------+
I know this seems like a silly way to store data, but it's just a simple example of what I really have. The table is formatted this way from a WordPress plugin, and I'd like to make it work without having to rewrite the plugin.
From what I've read, I can't use PIVOT with mySql. Is there something similar to PIVOT that I can use to achieve what I'm going for?
Try this pivot query:
SELECT id,
MAX(CASE WHEN field = 'first' THEN value ELSE NULL END) AS first,
MAX(CASE WHEN field = 'last' THEN value ELSE NULL END) AS last
FROM yourTable
GROUP BY id
Follow the link below for a running demo:
SQLFiddle
Try this;)
select
id,
max(if(field='first', value, null)) as first,
max(if(field='last', value, null)) as last
from yourtable
group by id
SQLFiddle DEMO HERE

implementing Some kind of pivot in mysql

I have a table in mysql in this structure
table: member
| Id | Name | Lastname | Username
| --------------------------------
| 1 | Alexi| Lalas | alexi
| 2 | Jack | Louis | louis
And I have a table called member images with this structre:
table: image
| Id | MemberId | Image | Type |
|------------------------------------|
| 50 | 1 | face.jpg |Avetar |
| 51 | 1 | image.jpg |Gallery|
| 52 | 2 | main.jpg |Avetar |
| 53 | 2 | jungle.jpg |Gallery|
And I want to get this result
| Id | Name | Lastname | Username | Image1 | Image2 |
|-------------------------------------------------------|
| 1 | Alexi| Lalas | alexi |face.jpg |image.jpg |
| 2 | Jack | Louis | louis |main.jpg |jungle.jpg|
Becuase of some reasons I can't handle is on app side and I have to do it on sql side.
Imagin that I always have 2 type of images and we always have Image1 and Image2.
Any help would be appritiated.
Since they are only two types, you can use the CASE expression to do so. Something like this:
SELECT
m.Id,
m.Name,
m.LastName,
m.UserName,
MAX(CASE WHEN i.Type = 'Avetar' THEN i.Image END) AS 'Image1',
MAX(CASE WHEN i.Type ='Gallery' THEN i.Image END) AS 'Image2'
FROM member AS m
LEFT JOIN image AS i ON m.Id = i.MemberId
GROUP BY m.Id,
m.Name,
m.LastName,
m.UserName;
Note that: LEFT JOIN will include all the members from the member table even if they have no images in the image table, in this case NULL will be returned.
See it in action here:
SQL Fiddle Demo
The way to do this is via a subselect (subquery). You would subselect the first column as the image for the user withe Avetar type and the other column subselect would be for the image with the type Gallery. If you can't find a way to make User ID and Type unique in your sub table then you are going to have issues with this type of query. Keep in mind that a subselects can impact performance heavily.
http://dev.mysql.com/doc/refman/5.0/en/subqueries.html

Sum column only if id is different

Hope everyone is doing well.
I have the following output...
+---------+--------------+--------------+-----------+---------+----------+
| ord_num | signoff_date | program_name | prod_desc | tx_comp | priority |
+---------+--------------+--------------+-----------+---------+----------+
| 1234567 | 2012-08-12 | ilearn | run | 1 | 1 |
| 1234567 | 2012-08-12 | ilearn | plan | 1 | 1 |
| 1234568 | 2012-08-12 | other | run | 1 | 1 |
| 1234569 | 2012-08-12 | other | run | 0 | 1 |
+---------+--------------+--------------+-----------+---------+----------+
What I would like to do is SUM the tx_comp column once per unique "ord_num".
Now I cant use GROUP BY ord_num as I also do a sum on the type of tasks.
Its like I need to know what the previous ord_num was then sum if different?
Any ideas would be greatly appreciated.
Thanks.
* EDIT *
SELECT
signoff_date,
SUM(IF(prod_desc = 'run', 1, 0)) AS run,
SUM(IF(prod_desc = 'plan', 1, 0)) AS plan,
SUM(tx_comp) AS tx_comp
FROM
(
SELECT
ord_num,
signoff_date,
program_name,
prod_desc,
tx_comp,
priority
FROM
test.orders
LEFT JOIN test.tx_comp USING (ord_num)
) AS grp
Obviously not the desired output
+--------------+------+------+---------+
| signoff_date | run | plan | tx_comp |
+--------------+------+------+---------+
| 2012-08-12 | 3 | 1 | 3 |
+--------------+------+------+---------+
I am after...
+--------------+------+------+---------+
| signoff_date | run | plan | tx_comp |
+--------------+------+------+---------+
| 2012-08-12 | 3 | 1 | 2 |
+--------------+------+------+---------+
If the value of tx_comp is always 1 or zero, then we can leverage COUNT(), which may give us more options. For instance, we can count the distinct ord_num where tx_comp is 1:
COUNT(distinct IF(tx_comp, ord_num, NULL))
Which gives me a final query of:
SELECT signoff_date,
SUM(IF(prod_desc = 'run', 1, 0)) AS run,
SUM(IF(prod_desc = 'plan', 1, 0)) AS plan,
COUNT(distinct IF(tx_comp, ord_num, NULL)) as tx_comp
FROM
test.orders
JOIN test.tx_comp USING (ord_num)
GROUP BY signoff_date
And there is no need for the subquery in this case. (edit: updated for your JOIN)
I have tested this with your sample data; the only dependency is on the semantic nature of tx_comp. You have been saying "SUM", and this assumes that the value will be at most 1 (I understand it to be a boolean flag, and in a comment on another answer you mentioned MAX(tx_comp) returning 1, so I think we're good).
Maybe just use MAX instead of SUM on the tx_comp column? I'm not sure about the semantics of your data, but I'm guessing that's what you want. In fact, it may be the same for run and plan as well.
For that matter, what you really want is BIT_OR, as you're working with booleans.