mysql format results as columns not rows - sql

Using MySQL Server, I have a table structure like:
(Table test)
id Name
1 "test1"
2 "test2"
3 "test3"
When I perform the following query:
Select name from test
the results are:
"test1"
"test2"
"test3"
How can I adjust this query so the results are columns, as such:
"test1" "test2" "test3"

Generally speaking, it's better to format your output in the application layer. Imagine that your table has 728003 unique values in the 'name' column. Your result would be unusably wide.
However, if you really want to do this and you have some unifying column to group on, you could do:
SELECT unifying_column, GROUP_CONCAT(DISTINCT name) FROM test
GROUP BY unifying_column;
ps, group_concat can only hold a limited number of characters
Addendum
The only way I could thing to do it with multiple columns would be something like this (and it is a horrible kludge):
SELECT SUBSTRING_INDEX(nlist,',',1) AS col1,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',2),',',-1) AS col2,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',3),',',-1) AS col3,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',4),',',-1) AS col4,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',5),',',-1) AS col5,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',6),',',-1) AS col6,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',7),',',-1) AS col7,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',8),',',-1) AS col8,
SUBSTRING_INDEX(SUBSTRING_INDEX(nlist,',',9),',',-1) AS col9,
SUBSTRING_INDEX(nlist,',',-1) AS col10
FROM
(SELECT unifying_column, GROUP_CONCAT(DISTINCT name LIMIT 10) AS nlist FROM test
GROUP BY unifying_column) AS subtable;
The above is not tested and may have syntax errors. I'm also not sure what it might do with the extra columns if there are fewer than 10 names.

Why you would need the data to be returned like that from the database?
If you actually need the data in that format it would make more sense to loop through the results and append them to a string to get the data in the format you require, but this should be done using a programming language instead of directly from the database.

Related

Speed up Oracle SQL Developer query in large Oracle Database

I am querying an Oracle DB using Oracle SQL Developer. The query is running slowly. I am away that using Distinct is likely slowing me down. But I haven't been able to produce unique rows without the Distinct call. The database contains no duplicate rows. So, it is likely that I malformed this query. How do I speed up this query? The query is as follows:
SELECT DISTINCT
view1.table1.col1,
view1.table2.col2,
view1.table2.col3,
view1.table1.col4,
view1.table3.col5,
view1.table4.col6
FROM
view1.table1,
view1.table3,
view1.table2,
view1.table4
WHERE
table1.col1 = table2.col7
AND
table1.col4 = table3.col8
AND
table1.col4 >= '19-DEC-20'
AND
table4.col9 = table3.col10 ```
table1: INDEX(col4, col1)
table3: INDEX(col8, col5, col10)
table2: INDEX(col7, col2, col3)
table4: INDEX(col9, col6)

How to duplicate records, modify and add them to same table

I got some question and hopefully you can help me out. :)
What I have is a table like this:
ID Col1 Col2 ReverseID
1 Number 1 Number A
2 Number 2 Number B
3 Number 3 Number C
What I want to achieve is:
Create duplicate of every record with switched columns and add them to original table
Add the ID of the duplicate to ReverseID column of original record and vice-versa
So the new table should look like:
ID Col1 Col2 ReverseID
1 Number 1 Number A 4
2 Number 2 Number B 5
3 Number 3 Number C 6
4 Number A Number 1 1
5 Number B Number 2 2
6 Number C Number 3 3
What I've done so far was working with temporary table:
SELECT * INTO #tbl
FROM myTable
UPDATE #tbl
SET Col1 = Col2,
Col2 = Col1,
ReverseID = ID
INSERT INTO DUPLICATEtable(
Col1,
Col2,
ReverseID
)
SELECT Col1,
Col2,
ReverseID
FROM #tbl
In this example code I used a secondary table just for making sure I do not compromise the original data records.
I think I could skip the SET-part and change the columns in the last SELECT statement to achieve the same, but I am not sure.
Anyway - with this I am ending up at:
ID Col1 Col2 ReverseID
1 Number 1 Number A
2 Number 2 Number B
3 Number 3 Number C
4 Number A Number 1 1
5 Number B Number 2 2
6 Number C Number 3 3
So the question remains: How do I get the ReverseIDs correctly added to original records?
As my SQL knowledge is pretty low I am almost sure, this is not the simplest way of doing things, so I hope you guys & girls can enlighten me and lead me to a more elegant solution.
Thank you in advance!
br
mrt
Edit:
I try to illustrate my initial problem, so this posting gets long. ;)
.
First of all: My frontend does not allow any SQL statements, I have to focus on classes, attributes, relations.
First root cause:
Instances of a class B (B1, B2, B3, ...) are linked together in class Relation, these are many-to-many relations of same class. My frontend does not allow join tables, so that's a workaround.
Stating a user adds a relation with B1 as first side (I just called it 'left') and B2 as second side (right):
Navigating from B1, there will be two relations showing up (FK_Left, FK_Right), but only one of them will contain a value (let's say FK_Left).
Navigating from B2, the value will be only listed in the other relation (FK_Right).
So from the users side, there are always two relations displayed, but it depends on how the record was entered, if one can find the data behind relation_left or relation_right.
That's no practicable usability.
If I had all records with vice-versa partners, I can just hide one of the relations and the user sees all information behind one relation, regardless how it was entered.
Second root cause:
The frontend provides some matrix view, which gets the relation class as input and displays left partners in columns and right partners in rows.
Let's say I want to see all instances of A in columns and their partners in rows, this is only possible, if all relations regarding the instances of A are entered the same way, e.g. all A-instances as left partner.
The matrix view shall be freely filterable regarding rows and columns, so if I had duplicate relations, I can filter on any of the partners in rows and columns.
sorry for the long text, I hope that made my situation a bit clearer.
I would suggest just using a view instead of trying to create and maintain two copies of the same data. Then you just select from the view instead of the base table.
create view MyReversedDataView as
select ID
, Col1
, Col2
from MyTable
UNION ALL
select ID
, Col2
, Col1
from MyTable
The trick to this kind of thing is to start with a SELECT that gets the data you need. In this case you need a resultset with Col1, Col2, reverseid.
SELECT Col2 Col1, Col1 Col1, ID reverseid
INTO #tmp FROM myTable;
Convince yourself it's correct -- swapped column values etc.
Then do this:
INSERT INTO myTable (Col1, col2, reverseid)
SELECT Col1, Col2, reverseid FROM #tmp;
If you're doing this from a GUI like ssms, don't forget to DROP TABLE #tmp;
BUT, you can get the same result with a pure query, without duplicating rows. Why do it this way?
You save the wasted space for the reversed rows.
You always get the reversed rows up to the last second, even if you forget to run the process for reversing and inserting them into the table.
There's no consistency problem if you insert or delete rows from the table.
Here's how you might do this.
SELECT Col1, Col2, null reverseid FROM myTable
UNION ALL
SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;
You can even make it into a view and use it as if it were a table going forward.
CREATE VIEW myTableWithReversals AS
SELECT Col1, Col2, null reverseid FROM myTable
UNION ALL
SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;
Then you can say SELECT * FROM myTableWithReversals WHERE Col1 = 'value' etc.
Let me assume that the id column is auto-incremented. Then, you can do this in two steps:
insert into myTable (Col1, Col2, reverseid)
select col2, col1, id
from myTable t
order by id; -- ensures that they go in in the right order
This inserts the new ids with the right reverseid. Now we have to update the previous values:
update t
set reverseid = tr.id
from myTable t join
myTable tr
on tr.reverseid = t.id;
Note that no temporary tables are needed.

Hive- how to get the derive column names and use it in the same query?

I am trying to run the below query :
select [every_column],count(*) from <table> group by [every_column] having count(*) >1
But column names should be derived in the same query. I believe show columns in would list down the column names separated by new line. But I need to use it in one query to retrieve the result.
Appreciate any help in this regard.
You can use shell sed to search the newlines(\n) and replace with comma(,).
Assign the comma separated column names to a hive variable, use the variable name in your hive query.
References for sed and set hive variables
Have you thought of using subqueries or even CTE? Maybe this helps you find your answer:
select outer.col1,
outer.col2,
outer.col3,
outer.col4,
outer.col5,
outer.col6, count(*) as cnt
from (
select <some logic> as col1,
<some logic> as col2,
<some logic> as col3,
<some logic> as col4,
<some logic> as col5,
<some logic> as col6
from innerTable
)outer
group by outer.col1,
outer.col2,
outer.col3,
outer.col4,
outer.col5,
outer.col6

How to define destination for an append query Microsoft Access

I'm trying to append two tables in MS Access at the moment. This is my SQL View of my Query at the moment:
INSERT INTO MainTable
SELECT
FROM Table1 INNER JOIN Table2 ON Table1.University = Table2.University;
Where "University" is the only field name that would have similarities between the two tables. When I try and run the query, I get this error:
Query must have at least one destination field.
I assumed that the INSERT INTO MainTable portion of my SQL was defining the destination, but apparently I am wrong. How can I specify my destination?
You must select something from your select statement.
INSERT INTO MainTable
SELECT col1, col2
FROM Table1 INNER JOIN Table2 ON Table1.University = Table2.University;
Besides Luke Ford's answer (which is correct), there's another gotcha to consider:
MS Access (at least Access 2000, where I just tested it) seems to match the columns by name.
In other words, when you execute the query from Luke's answer:
INSERT INTO MainTable
SELECT col1, col2
FROM ...
...MS Access assumes that MainTable has two columns named col1 and col2, and tries to insert col1 from your query into col1 in MainTable, and so on.
If the column names in MainTable are different, you need to specify them in the INSERT clause.
Let's say the columns in MainTable are named foo and bar, then the query needs to look like this:
INSERT INTO MainTable (foo, bar)
SELECT col1, col2
FROM ...
As other users have mentioned, your SELECT statement is empty. If you'd like to select more that just col1, col2, however, that is possible. If you want to select all columns in your two tables that are to be appended, you can use SELECT *, which will select everything in the tables.

SQL Server 2008 - Case / If statements in SELECT Clause [duplicate]

This question already has answers here:
How do I perform an IF...THEN in an SQL SELECT?
(29 answers)
Closed 9 years ago.
I have a Query that's supposed to run like this -
If(var = xyz)
SELECT col1, col2
ELSE IF(var = zyx)
SELECT col2, col3
ELSE
SELECT col7,col8
FROM
.
.
.
How do I achieve this in T-SQL without writing separate queries for each clause? Currently I'm running it as
IF (var = xyz) {
Query1
}
ELSE IF (var = zyx) {
Query2
}
ELSE {
Query3
}
That's just a lot of redundant code just to select different columns depending on a value.
Any alternatives?
You are looking for the CASE statement
http://msdn.microsoft.com/en-us/library/ms181765.aspx
Example copied from MSDN:
USE AdventureWorks;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
Just a note here that you may actually be better off having 3 separate SELECTS for reasons of optimization. If you have one single SELECT then the generated plan will have to project all columns col1, col2, col3, col7, col8 etc, although, depending on the value of the runtime #var, only some are needed. This may result in plans that do unnecessary clustered index lookups because the non-clustered index Doesn't cover all columns projected by the SELECT.
On the other hand 3 separate SELECTS, each projecting the needed columns only may benefit from non-clustered indexes that cover just your projected column in each case.
Of course this depends on the actual schema of your data model and the exact queries, but this is just a heads up so you don't bring the imperative thinking mind frame of procedural programming to the declarative world of SQL.
Try something like
SELECT
CASE var
WHEN xyz THEN col1
WHEN zyx THEN col2
ELSE col7
END AS col1,
...
In other words, use a conditional expression to select the value, then rename the column.
Alternately, you could build up some sort of dynamic SQL hack to share the query tail; I've done this with iBatis before.
Simple CASE expression:
CASE input_expression
WHEN when_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
Searched CASE expression:
CASE
WHEN Boolean_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
Reference: http://msdn.microsoft.com/en-us/library/ms181765.aspx
CASE is the answer, but you will need to have a separate case statement for each column you want returned. As long as the WHERE clause is the same, there won't be much benefit separating it out into multiple queries.
Example:
SELECT
CASE #var
WHEN 'xyz' THEN col1
WHEN 'zyx' THEN col2
ELSE col7
END,
CASE #var
WHEN 'xyz' THEN col2
WHEN 'zyx' THEN col3
ELSE col8
END
FROM Table
...
The most obvious solutions are already listed. Depending on where the query is sat (i.e. in application code) you can't always use IF statements and the inline CASE statements can get painful where lots of columns become conditional.
Assuming Col1 + Col3 + Col7 are the same type, and likewise Col2, Col4 + Col8 you can do this:
SELECT Col1, Col2 FROM tbl WHERE #Var LIKE 'xyz'
UNION ALL
SELECT Col3, Col4 FROM tbl WHERE #Var LIKE 'zyx'
UNION ALL
SELECT Col7, Col8 FROM tbl WHERE #Var NOT LIKE 'xyz' AND #Var NOT LIKE 'zyx'
As this is a single command there are several performance benefits with regard to plan caching. Also the Query Optimiser will quickly eliminate those statements where #Var doesn't match the appropriate value without touching the storage engine.