please help me i have columns from more than one table and the data type for all these columns is integer
i want to sort the data row (not columns (not order by)) Except the primary key column
for example
column1(pk) column2 column3 column4 column5
1 6 5 3 1
2 10 2 3 1
3 1 2 4 3
How do I get this result
column1(pk) column2 column3 column4 column5
1 1 3 5 6
2 1 2 3 10
3 1 2 3 4
Please help me quickly .. Is it possible ?? or impossible ???
if impossible how I could have a similar result regardless of sort
What database are you using? The capabilities of the database are important. Second, this suggests a data structure issue. Things that need to be sorted would normally be separate entities . . . that is, separate rows in a table. The rest of this post answers the question.
If the database supports pivot/unpivot you can do the following:
(1) Unpivot the data to get in the format , ,
(2) Use row_number() to assign a new column, based on the ordering of the values.
(3) Use the row_number() to create a varchar new column name.
(4) Pivot the data again using the new column.
You can do something similar if this functionality is not available.
First, change the data to rows:
(select id, 'col1', col1 as val from t) union all
(select id, 'col2', col2 from t) union all
. . .
Call this byrow. The following query appends a row number:
select br.*, row_number() over (partition by id order by val) as seqnum
from byrow br
Put this into a subquery to unpivot. The final solution looks like:
with byrow as (<the big union all query>)
select id,
max(case when seqnum = 1 then val end) as col1,
max(case when seqnum = 2 then val end) as col2,
...
from (select br.*, row_number() over (partition by id order by val) as seqnum
from byrow br
) br
group by id
You can use pivot function of sql server to convert the row in column. Apply the sorting there and again convert column to row using unpivot.
Here is a good example using PIVOT, you should be able to adapt this to meet your needs
http://blogs.msdn.com/b/spike/archive/2009/03/03/pivot-tables-in-sql-server-a-simple-sample.aspx
Related
I am a beginner in SQL and unfortunately I am not being able to solve a problem. I have a list of column names in a system table which I want to insert into separate rows of a table based on the serial of the column name.
Original table:
Column name
001000
001100
001200
002000
002100
002200
002300
Target table:
Column 1
Column 2
Column 3
Column 4
001000
001100
001200
NULL
002000
002100
002200
002300
......
......
......
......
022000
022100
022200
022300
There are a large number of rows in the original table so it is quite challenging to separate the numbers into groups. I have looked into the PIVOT function but that does not solve this issue.
Unfortunately, as I am a beginner, I am also not able to put it into code to begin with. Any help with recommending which functions I should look into so that I can start writing some code on this would be really helpful. Any pointers towards a solution is also highly appreciated.
Conditional aggregation should do what you want:
select max(case when seqnum = 1 then column end),
max(case when seqnum = 2 then column end),
max(case when seqnum = 3 then column end),
max(case when seqnum = 4 then column end)
from (select t.*,
row_number() over (partition by left(column, 3) order by column) as seqnum
from t
) t
group by left(column, 3)
Can't wrap my mind around the next task:
I have a table, with some key, which represents some kind of group id. I would like to GROUP BY by this key and in resulted table show some columns from this table depending on the column value:
If all the values in this group by this key in col1 are equal (same number or text), then show this exact value, if they are different (at least one of them) - show some kind like "Others".
Example
key col1
1 1
1 1
1 1
2 4
2 5
Resulted table:
key col1
1 1
2 Others
Postgres 9.4, if this matters.
You can use aggregation and case:
select key,
(case when min(col1) = max(col1) then min(col1)
else 'others'
end) as col1
from t
group by key;
I have the task to find out if all columns in a SQL Server table have exact the same value. The table content is created by a stored procedure and can vary in the number of columns. The first column is an ID, the second and the following columns must be compared if the all columns have exact the same value.
At the moment I do not have a clue how to achieve this.
The best solution would be to display only the rows, which have different values in one or multiple columns except the first column with ID.
Thank you so much for your help!!
--> Edit: The table looks this:
ID Instance1 Instance2 Instance3 Instance4 Instance5
=====================================================
A 1 1 1 1 1
B 1 1 0 1 1
C 55 55 55 55 55
D Driver Driver Driver Co-driver Driver
E 90 0 90 0 50
F On On On On On
The result should look like this, only the rows with one or multiple different column values should be display.
ID Instance1 Instance2 Instance3 Instance4 Instance5
=====================================================
B 1 1 0 1 1
D Driver Driver Driver Co-driver Driver
E 90 0 90 0 50
My table has more than 1000 rows and 40 columns
you can achieve this by using row_number()
Try the following code
With c as(
Select id
,field_1
,field_2
,field_3
,field_n
,row_number() over(partition by field_1,field_2,field_3,field_n order by id asc) as rn
From Table
)
Select *
From c
Where rn = 1
row_number with partition is going to show you if the field is repeated by assigning a number to a row based on field_1,field_2,field_3,field_n, for example if you have 2 rows with same field values the inner query is going to show you
rn field_1 field_2 field_3 field_n id
1 x y z a 5
2 x y z a 9
After that on the outer part of the query pick rn = 1 and you are going to obtain a query without repetitions based on fields.
Also if you want to delete repeated numbers from your table you can apply
With c as(
Select id
,field_1
,field_2
,field_3
,field_n
,row_number() over(partition by field_1,field_2,field_3,field_n order by id asc) as rn
From Table
)
delete
From c
Where rn > 1
The best solution would be to display only the rows, which have different values in one or multiple columns except the first column with ID.
You may be looking for a the following simple query, whose WHERE clause filters out rows where all fields have the same value (I assumed 5 fields - id not included).
SELECT *
FROM mytable t
WHERE NOT (
field1 = field2
AND field1 = field3
AND field1 = field4
AND field1 = field5
);
I have this table (short example) with two columns
1 a
2 a
3 a3
4 a
5 a
6 a6
7 a
8 a8
9 a
and I would like to group/partition them into groups separated by those leading "a", ideally to add another column like this, so I can address those groups easily.
1 a 0
2 a 0
3 a3 3
4 a 3
5 a 3
6 a6 6
7 a 6
8 a8 8
9 a 8
problem is that setup of the table is dynamic so I can't use staticly lag or lead functions, any ideas how to do this without pl/sql in postgres version 9.5
Assuming the leading part is a single character. Hence the expression right(data, -1) works to extract the group name. Adapt to your actual prefix.
The solution uses two window functions, which can't be nested. So we need a subquery or a CTE.
SELECT id, data
, COALESCE(first_value(grp) OVER (PARTITION BY grp_nr ORDER BY id), '0') AS grp
FROM (
SELECT *, NULLIF(right(data, -1), '') AS grp
, count(NULLIF(right(data, -1), '')) OVER (ORDER BY id) AS grp_nr
FROM tbl
) sub;
Produces your desired result exactly.
NULLIF(right(data, -1), '') to get the effective group name or NULL if none.
count() only counts non-null values, so we get a higher count for every new group in the subquery.
In the outer query, we take the first grp value per grp_nr as group name and default to '0' with COALESCE for the first group without name (which has a NULL as group name so far).
We could use min() or max() as outer window function as well, since there is only one non-null value per partition anyway. first_value() is probably cheapest since the rows are sorted already.
Note the group name grp is data type text. You may want to cast to integer, if those are clean (and reliably) integer numbers.
This can be achieved by setting rows containing a to a specific value and all the other rows to a different value. Then use a cumulative sum to get the desired number for the rows. The group number is set to the next number when a new value in the val column is encountered and all the proceeding rows with a will have the same group number as the one before and this continues.
I assume that you would need a distinct number for each group and the number doesn't matter.
select id, val, sum(ex) over(order by id) cm_sum
from (select t.*
,case when val = 'a' then 0 else 1 end ex
from t) x
The result for the query above with the data in question, would be
id val cm_sum
--------------
1 a 0
2 a 0
3 a3 1
4 a 1
5 a 1
6 a6 2
7 a 2
8 a8 3
9 a 3
With the given data, you can use a cumulative max:
select . . .,
coalesce(max(substr(col2, 2)) over (order by col1), 0)
If you don't strictly want the maximum, then it gets a bit more difficult. The ANSI solution is to use the IGNORE NULLs option on LAG(). However, Postgres does not (yet) support that. An alternative is:
select . . ., coalesce(substr(reft.col2, 2), 0)
from (select . . .,
max(case when col2 like 'a_%' then col1 end) over (order by col1) as ref_col1
from t
) tt join
t reft
on tt.ref_col1 = reft.col1
You can also try this :
with mytable as (select split_part(t,' ',1)::integer id,split_part(t,' ',2) myvalue
from (select unnest(string_to_array($$1 a;2 a;3 a3;4 a;5 a;6 a6;7 a;8 a8;9 a$$,
';'))t) a)
select id,myvalue,myresult from mytable join (
select COALESCE(NULLIF(substr(myvalue,2),''),'0') myresult,idmin id_down
,COALESCE(lead(idmin) over (order by myvalue),999999999999) id_up
from (
select myvalue,min(id) idmin from mytable group by 1
) a) b
on id between id_down and id_up-1
In Google Spreadsheet I have such table:
A B C
----------------
One [0] 3 2
Two [1] 6 0
Three [5] 1 1
Four [3] 1 2
Five [2] 1 0
I would like to generate SORT() or QUERY() which will return a two-column table sorted by a sum of B and C. Also the A column should be substringed to drop last four characters.
So the result should be:
Two 6
One 5
Four 3
Three 2
Five 1
I tried with SELECT MID(A,1,-5), (B+C) ORDER BY B+C but the executions is pretty bad. All suggestions welcome! Thank you in advance!
Alternatively, also try (in google spreadsheet)
=query({ArrayFormula(regexextract(A2:A, "^(.+) \[")), B2:C}, "Select Col1, sum(Col2)+sum(Col3) where Col2 is not null group by Col1 order by sum(Col2)+sum(Col3) label sum(Col2)+sum(Col3)''",0)
or, depending on your locale:
=query({ArrayFormula(regexextract(A2:A; "^(.+) \["))\ B2:C}; "Select Col1, sum(Col2)+sum(Col3) where Col2 is not null group by Col1 order by sum(Col2)+sum(Col3) label sum(Col2)+sum(Col3)''";0)
Also see this example spreadsheet.
This will help you
=QUERY(B2:D7,"Select B,SUM(C)+SUM(D) group by B order by SUM(C)+SUM(D) desc label SUM(C)+SUM(D) 'SUM'")
If you are new to SQL ,
Group By Clause : Whenever we use aggregate functions such as MAX,
MIN, SUM,COUNT,AVG we will be using GROUP BY clause.
Label is used to rename the column name like the AS keyword in SQL.
ORDER BY clause is used to sort desc or asc.
Example Spreadsheet link
If you are using mysql You an use sugstrin_index because your a string part is not fixed lenght
select SUBSTRING_INDEX(a,' ',1) as A , b+c as C
from your_table
order by C DESC
fro sqlserver you can use substring
select SUBSTRING(a, 1, instr(String," ") -1) as A , b+c as C
from your_table
order by C DESC
If you're using SQL, try this:
SELECT
LEFT(A,LEN(A)-4) AS Col1
,(B+C) AS Col2
FROM table
ORDER BY Col2 DESC