4

Forgive me if this question has been asked and answered, I've searched and found a few that look similar but I'm too much of a novice with SQL to adapt them to my needs. Also forgive me if I don't use the correct terminology, I know it can be annoying when someone asks a question and they don't even know enough to be able to ask for what they need.

<2nd EDIT Mar22:>

Ok, I didn't understand what the source data actually looked like, and that is why I couldn't get what I wanted. Thanks to @goran for pushing me to get the real source tables to post here (which I'm still not going to post because I'm too lazy to redact them as appropriate for easy viewing and protection of the innocent, but I should have at least printed them out before asking). Below are newly revised example tables, but I still haven't figure out how to achieve the end goal of getting everything into a single row.

table_one:

id  name          total
5   John Doe      20

table_two:

id  product_id    price
5   51            17

table_three:

id  text       number
5   Subtotal   17
5   Tax        3
5   Total      20

What I'm looking for is something like this:

id name     total product_id price text     number text number text   number
5  John Doe 20    51         17    Subtotal 17     Tax  3      Total  20

I'm no longer certain how valid the information below is, but I'm leaving it here for the moment, hoping it won't confuse new readers of the question too much.

</EDIT Mar 22>

I'm helping a friend gather some data, and need to perform a query that results in a single row per record, but instead I get multiple rows. Here is an example of what I'm querying right now (simplified, hopefully not too much):

SELECT * FROM `table_one` AS t1 
INNER JOIN `table_two` AS t2 ON t1.id = t2.id 
INNER JOIN `table_three` AS t3 ON t1.id = t3.id 
WHERE 1

The result is:

id  text       number
5   Subtotal   17
5   Tax        3
5   Total      20

What I need is to create a query that results in something more like this:

id  text       number  text  number  text   number
5   subtotal   17      Tax   3       Total  20

Any assistance/guidance would be much appreciated.

Thanks!

--jed

OMG Ponies
  • 325,700
  • 82
  • 523
  • 502
Jed Daniels
  • 24,376
  • 5
  • 24
  • 24
  • Do you have the Subtotal, tax, and total in different tables? or are you trying to combine the tables that each have subtotal, tax, total? I think your example query was too simplified, seeing the real one would be helpful. – Justin Jenkins Mar 21 '10 at 00:13
  • Yes, sorry, I will edit to clarify. – Jed Daniels Mar 22 '10 at 17:03
  • The query you quoted, results and sample data do not match. Why don't you copy paste actual queries and results? P.S. If you really want a guaranteed definitive answer you could also mysqldump -c -n database table1 table2 table3 > table.sql and then copy/paste relevant INSERTS and relevant parts of CREATE TABLE statements if it is not too long. – Unreason Mar 22 '10 at 17:22
  • @goran: Thanks for being persistent and putting up with me. I will copy and paste the actual queries and results momentarily. Thanks again, --jed – Jed Daniels Mar 22 '10 at 18:03
  • @goran: Ok, just trying to get the real tables has show me the error of my ways. I had mistakenly assumed that each table had a different element that I wanted to combine, but one table has multiple rows that I need combined, and is the reason things aren't turning out the way I expected. Moral of the story: make sure you understand what the source data looks like before you assume the results are incorrect. I'll update the question soon with more information. – Jed Daniels Mar 22 '10 at 18:26
  • ah, then id is not really the primary key there :) that's also throwing off the track... anyway, update, and we'll take another hack at it – Unreason Mar 22 '10 at 20:11
  • @goran, I've updated with the latest I've got (essentially replaced the contents of my last update). I know I'm a n00b at this, and I appreciate you sticking through it with me. Worst case is I just output the three tables individually and make things the way I want with a python or bash script, but I'd prefer to be better educated on MySQL. – Jed Daniels Mar 22 '10 at 20:26

3 Answers3

4

I think you did simplify it too much somewhere. The query you quote would return exactly what you want already. Here's an example (selecting from single table twice gives similar situation as what you have)

mysql> select * from test t1 join test t2 on t1.a = t2.a LIMIT 1,5;
+------+------+------+------+
| a    | b    | a    | b    |
+------+------+------+------+
|    1 |    2 |    1 |    1 | 
|    1 |    1 |    1 |    2 | 
|    1 |    2 |    1 |    2 | 
|    2 |    2 |    2 |    2 | 
|    2 |    2 |    2 |    2 | 
+------+------+------+------+
5 rows in set (0.00 sec)

Mysql has no problem to label the result set columns with same labels. I guess that your original query had select t1.* in select part.

If you want to refer to individual fields whose names are ambiguous you'll get

mysql> select a from test t1 join test t2 on t1.a = t2.a LIMIT 1,5;
ERROR 1052 (23000): Column 'a' in field list is ambiguous

And you have to specify exactly what you want (column aliases are optional, you can do t1., t2. as well)

mysql> select t1.a first, t2.a second from test t1 join test t2 on t1.a = t2.a LIMIT 1,5;
+-------+--------+
| first | second |
+-------+--------+
|     1 |      1 | 
|     1 |      1 | 
|     1 |      1 | 
|     2 |      2 | 
|     2 |      2 | 
+-------+--------+
5 rows in set (0.00 sec)

Edit 22MAR After a change in the sample data it seems that you want to turn several rows from one table into one. Here is a particular solution (assuming that you'll always have Tax, Total and Subtotal rows and that you are only interested in these rows).

SELECT t1.id, t1.name, t2.product_id, t2.price, t3a.number subtotal, t3b.number total, t3c.number tax
FROM `table_one` AS t1 
INNER JOIN `table_two` AS t2 ON t1.id = t2.id 
INNER JOIN `table_three` AS t3a ON t1.id = t3a.id and t3a.text = "Subtotal"
INNER JOIN `table_three` AS t3b on t3a.id = t3b.id and t3b.text = "Total"
INNER JOIN `table_three` AS t3c on t3b.id = t3c.id and t3c.text = "Tax"

(if you want you can also select constants "Tax", "Total" and "Subtotal" in the select part and give them some column names)

One thing that remains unclear is the relationship between id's in tables - are they primary key of table_one or table_two. That can influence the results, of course, when you will have multiple rows in table_one and table_two.

Unreason
  • 12,556
  • 2
  • 34
  • 50
  • I didn't really simplify the query, only the results (the real results have about 50 columns), although I changed the names of the tables to make things a little easier (they names were orders, orders_total and orders_products). I'm not sure I completely understand your examples, as the first is clearly selecting from a single table, where as I am trying to merge the output from three tables together, (eliminating duplicates that are equal and replicating duplicates that aren't). Thanks, --jed – Jed Daniels Mar 22 '10 at 17:02
  • My example shows a) that there is no problem with same labels for column names in mysql client b) how to use aliases – Unreason Mar 22 '10 at 17:25
  • @goran: "One thing that remains unclear is the relationship between id's in tables - are they primary key of table_one or table_two." I honestly don't know. I'm pretty sure that table_one and table_two will each have only one row per id. Thanks again for your answers, I'm pretty sure I can make your revised example work, so it'll solve my problem without needing any additional scripting. --jed – Jed Daniels Mar 22 '10 at 22:02
  • glad to help, still if you don't know how your tables are related you can't really say that you are on the right track. :) – Unreason Mar 22 '10 at 22:47
1

You won't be able to get your result exactly as you want to at least because you have columns with the same names. Probably you may be able to get this result having the columns renamed but this approach will lead to hacky code and inability of proper result usage.

You should reconsider the further use of the records returned and update it in order to process the actual result as soon as it is the way SQL select should return data normally.

Li0liQ
  • 11,158
  • 35
  • 52
1

The output you're asking for is not a relation, since its attributes don't have unique names. So it's unreasonable to expect a relational database system to produce such a result. Which is not to say that some database systems can break the relational model and produce non-relational results in some cases; but this isn't likely to be one of them.

So you should instead have the application take the relation as input and transform it to the output you want. From the RDBMS perspective, that's a major part of the role of the application.

bignose
  • 30,281
  • 14
  • 77
  • 110
  • I can accept this answer, and I'm willing to transform the data with a script, but if there were a way to make MySQL output things in a way that is close to what I need, that would be best. Thanks much, --jed – Jed Daniels Mar 22 '10 at 17:12