How should I order a subset of a query returned and place it on the top of the result? - sql

I have a query for example:
select name from tableA;
which gives the following:
a
b
c
d1
d2
d3
e1
e3
I would like to have it ordered with the "d's" on top of the list.
e.g.
d1
d2
d3
a
b
c
e1
e2
e3
I tried to do a union with two queries but it seems to not be working. I believe I'm missing something but can't figure it out.
I got this far:
select name from tableA where name like 'd%';
union
select name from tableA;

You can try using a CASE statement in the ORDER BY clause:
SQL Fiddle
SELECT name
FROM TableA
ORDER BY
CASE WHEN name LIKE 'd%' THEN 0 ELSE 1 END,
name

Related

An SQL chalenge

I would like to solve this with pure SQL sentences in an AMDP method, I could solve this easily in ABAP, even in an AMDP method using loops, but as I said, I would like to solve this with SQL sentences, without use any kind of loops.
Please take a look on this image:
I have 2 columns, the first I'll name as D and the second as E
The D column, is a result of a SELECT SUM, but the E column, is a calculated column, and it should work as follow:
First line both columns are equal E1 = D1
In the second line, E2 = E1 + D2
In the third line, E3 = E2 + D3
In the forth line, E4 = E3 + D4
And so on.
So that's it. Is it possible to solve this with pure SQL sentences?
Have the SUM in a subquery, then do a select from that subquery along with a row number. Insert that into a temporary table. Then select from that temporary table and do a join to the same table based on the row number, looking for the previous row.
SELECT D, ROW_NUMBER() AS ROW_NUM
INTO #TempTable
FROM (SELECT SUM() AS D FROM table) a
SELECT
t1.D
,CASE
t2.D IS NULL THEN t1.D
ELSE t2.D + t1.D AS E
FROM #TempTable t1
LEFT JOIN #TempTable t2 ON t1.ROW_NUM = t2.ROW_NUM + 1

Select entries that have non repeating values on a specific column (although other columns may have repeating or non repeating values) (SQL)

Let's say I have the following table:
A
B
C
D
a1
b1
c1
d1
a1
b1
c1
d2
a2
b2
c3
d3
a2
b2
c4
d3
I want to filter and see all four columns for entries that have the same value con column A but different on column C, so I get only this as a result:
A
B
C
D
a2
b2
c3
d3
a2
b2
c4
d3
I don't really care if values con columns B and D are the same or different, although I would like to have them in my table to do further analysis later.
Using the DISTINCT statement would give me all the columns as a result, as they all are different in some column, so that doesn't work for me.
I read some questions (like this one) and the answers recommended using the row_number() over(partition by...) clause, although the use they gave it doesn't quite fit my problem (I think), as it would also return the first row with a repeating value on column C.
Any ideas how this could be done?
You can use exists:
select t.*
from t
where exists (select 1
from t t2
where t2.a = t.a and t2.c <> t.c
)
order by t.a;
You could use a self join
select t1.*
from t t1
join t t2 on t1.a=t2.a and t1.c<>t2.c

Aggregate and concatenate from two tables based on comparison between columns

I have two tables like this:
Table1
A T
a1 t1
a2 t2
a3 t3
a4 t4
a5 t5
...
...
Table2
E T
e1 t1
e2 t2
e3 t3
e4 t4
e5 t5
...
...
what I wanted to achieve is this:
Table 3
E A'
e1 a1,a2,a3
e2 a4,a5,a6
...
...
The aggregation A' is done like this: In table 2 for each e there is a value in column T : t and with that t you look for the last 3 values in Table 1 that are less than the t in question. So a1, a2, a3 are values of A whose t values are less than t1 in Table 2 whose E is e1.
I know that I could write two queries for this like this:
ResultSet (rt) -> select t from e
and then iterate ResultSet and do something like this :
select A from Table1 where t < rt[i] limit 3 - not sure how to concatenate here :)
but I m pretty sure this is utterly inefficient. There should be a better way to do this.
I m working with Postgresql.
If it had been a dataframe from a file I would use python's pandas. Also I know that python has read_sql but the tables are very huge I don't want to load the whole table in memory which I think it won't but not sure either - anyway its a separate story.
How do we solve this in SQL? Any ideas please.
In table 2 for each e there is a value in column T : t and with that t you look for the last 3 values in Table 1 that are less than the t in question.
I don't understand the results follow this logic. But based on your description, you can use a lateral join:
select t2.*, t1.the_as
from t2 left join lateral
(select array_agg(t1.a) as the_as
from (select t1.*
from t1
where t1.T <= t2.T
order by t1.T desc
limit 3
) t1
) t1
on 1=1;
Note that this uses arrays rather than strings because I think arrays are a better data structure for storing multiple values. That said, you can just use string_agg() instead, if you really want a string. The syntax would be string_agg(t1.a, ',').

Access SQL Query to search value in 2 tables but use just one?

I have 2 tables in MS Access and need to query them looking for a value. If the value is in A, then use that. If value is in B, then use that. If the value is in both tables, then use only the value from table A.
How can I make a query to do that?
Thanks!
How about:
SELECT IIF(IsNull(AField),(SELECT AField FROM Table2 WHERE ID=16), AField)
FROM Table1
WHERE ID=16
If you want to do an entire table rather than 1 row :-
select C1, C2 from TableA where C2 is not null
union all
select C1, C2 from TableB where C1 in ( select c1 from TableA where C2 is null )

SQL Multiple Tables

I have 2 sets of 2 corresponding tables (4 tables total). The two sets only correspond in one column. I want the query to search through that one column in both joined tables, and be able to return the value in the selected column, even if that column doesn't exist in the other table.
Currently, my query looks like:
select z
FROM A1
INNER JOIN A2
ON A1.x=A2.x
WHERE A1.x= '25'
UNION
select z
FROM B1
INNER JOIN B2
ON B1.x=B2.x
WHERE B1.x= '25'
UNION works as long as I am looking for a column which both (joined) tables A and B have in common. I'd like to be able to get values from columns which only exist in A or in B, but not necessarily both of them.
Thanks in advance.
Edit:
Basically, I want two completely separate queries on separate tables, but in one query, with only one select.
Example:
Table A1
x | y
------
1 | a
2 | b
Table A2
x | z
------
1 | c
2 | d
Table B1
x | v
------
3 | e
4 | f
Table B2
x | w
------
3 | g
4 | h
So I want look for a column variable (such as v,w,y, or z), with a specified value of x. e.g. select w where x=4 should give me h; select z where x=2 should give me d.
You must have the same number of columns in each select statement when using UNION. You can add constant values for columns that are missing. You must also have the same data type for each column.
select Column1, null as Column2
from T1
union
select '', Column2
from T2
As per comment by #Adrian, you can of course use null as a constant value. Otherwise you need to pick a constant value of the data type that is used for the column.
select Column1, null as Column2
from T1
union
select null, Column2
from T2
Use the sample data provided in the question:
select A1.x, A2.z as 'y'
from A1
inner join A2
on A1.x=A2.x
where A1.x= 4
union
select B1.x, B2.w as 'y'
from B1
inner join B2
on B1.x=B2.x
where B1.x= 4
Result:
x y
4 h
With a 2 instead of a 4
Result:
x y
2 d
It would be something like that:
select Column1, ColumnThatOnlyExistsInContextA, null as ColumnThatOnlyExistsInContextB
FROM A1
INNER JOIN A2
ON A1.ID=A2.ID
WHERE A1.ID= '25'
UNION
select Column1, null, ColumnThatOnlyExistsInContextB
FROM B1
INNER JOIN B2
ON B1.ID=B2.ID
WHERE B1.ID= '25'
When using UNION, make sure all queries return result sets that have the same number of columns with the same type. If you want to return a column from the second query in a union that the first query doesn't have, you can modify your first query to have a NULL value for that column.
So you basically want to do:
select Column1
FROM A1
INNER JOIN A2
ON A1.ID=A2.ID
WHERE A1.ID= '25'
UNION
select Column2
FROM B1
INNER JOIN B2
ON B1.ID=B2.ID
WHERE B1.ID= '25'
right?
If so, your problem is probably just that Column1 and Column2 are different types. So, do something like
select cast(Column1 as varchar(255))
and
select cast(Column2 as varchar(255))
Should work!
Well, UNION's only requirement is that the number and type of the fields in each result set being UNIONed must match. So, if B has a Column2 and A doesn't, you can select Column1 from the joined As and Column2 from the joined Bs, and provided A.Column1 and B.Column2 are the same type (you can CAST or CONVERT if necessary) the statement will still work. Maybe I'm not understanding the problem, but I think it's pretty easy to solve.