What is the best way of transcribing the following Transact-SQL code to Informix Dynamic Server (IDS) 9.40:
Objective: I need the first 50 orders with their respective order lines
select *
from (select top 50 * from orders) a inner join lines b
on a.idOrder = b.idOrder
My problem is with the subselect because Informix does not allow the FIRST option in the subselect.
Any simple idea?.
The official answer would be 'Please upgrade from IDS 9.40 since it is no longer supported by IBM'. That is, IDS 9.40 is not a current version - and should (ideally) not be used.
Solution for IDS 11.50
Using IDS 11.50, I can write:
SELECT *
FROM (SELECT FIRST 10 * FROM elements) AS e
INNER JOIN compound_component AS a
ON e.symbol = a.element
INNER JOIN compound AS c
ON c.compound_id = a.compound_id
;
This is more or less equivalent to your query. Consequently, if you use a current version of IDS, you can write the query using almost the same notation as in Transact-SQL (using FIRST in place of TOP).
Solution for IDS 9.40
What can you do in IDS 9.40? Excuse me a moment...I have to run up my IDS 9.40.xC7 server (this fix pack was released in 2005; the original release was probably in late 2003)...
First problem - IDS 9.40 does not allow sub-queries in the FROM clause.
Second problem - IDS 9.40 does not allow 'FIRST n' notation in either of these contexts:
SELECT FIRST 10 * FROM elements INTO TEMP e;
INSERT INTO e SELECT FIRST 10 * FROM elements;
Third problem - IDS 9.40 doesn't have a simple ROWNUM.
So, to work around these, we can write (using a temporary table - we'll remove that later):
SELECT e1.*
FROM elements AS e1, elements AS e2
WHERE e1.atomic_number >= e2.atomic_number
GROUP BY e1.atomic_number, e1.symbol, e1.name, e1.atomic_weight, e1.stable
HAVING COUNT(*) <= 10
INTO TEMP e;
SELECT *
FROM e INNER JOIN compound_component AS a
ON e.symbol = a.element
INNER JOIN compound AS c
ON c.compound_id = a.compound_id;
This produces the same answer as the single query in IDS 11.50. Can we avoid the temporary table? Yes, but it is more verbose:
SELECT e1.*, a.*, c.*
FROM elements AS e1, elements AS e2, compound_component AS a,
compound AS c
WHERE e1.atomic_number >= e2.atomic_number
AND e1.symbol = a.element
AND c.compound_id = a.compound_id
GROUP BY e1.atomic_number, e1.symbol, e1.name, e1.atomic_weight,
e1.stable, a.compound_id, a.element, a.seq_num,
a.multiplicity, c.compound_id, c.name
HAVING COUNT(*) <= 10;
Applying that to the original orders plus order lines example is left as an exercise for the reader.
Relevant subset of schema for 'Table of Elements':
-- See: http://www.webelements.com/ for elements.
-- See: http://ie.lbl.gov/education/isotopes.htm for isotopes.
CREATE TABLE elements
(
atomic_number INTEGER NOT NULL UNIQUE CONSTRAINT c1_elements
CHECK (atomic_number > 0 AND atomic_number < 120),
symbol CHAR(3) NOT NULL UNIQUE CONSTRAINT c2_elements,
name CHAR(20) NOT NULL UNIQUE CONSTRAINT c3_elements,
atomic_weight DECIMAL(8,4) NOT NULL,
stable CHAR(1) DEFAULT 'Y' NOT NULL
CHECK (stable IN ('Y', 'N'))
);
CREATE TABLE compound
(
compound_id SERIAL NOT NULL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE
);
-- The sequence number is used to order the components within a compound.
CREATE TABLE compound_component
(
compound_id INTEGER REFERENCES compound,
element CHAR(3) NOT NULL REFERENCES elements(symbol),
seq_num SMALLINT DEFAULT 1 NOT NULL
CHECK (seq_num > 0 AND seq_num < 20),
multiplicity INTEGER NOT NULL
CHECK (multiplicity > 0 AND multiplicity < 20),
PRIMARY KEY(compound_id, seq_num)
);
Output (on my sample database):
1 H Hydrogen 1.0079 Y 1 H 1 2 1 water
1 H Hydrogen 1.0079 Y 3 H 2 4 3 methane
1 H Hydrogen 1.0079 Y 4 H 2 6 4 ethane
1 H Hydrogen 1.0079 Y 5 H 2 8 5 propane
1 H Hydrogen 1.0079 Y 6 H 2 10 6 butane
1 H Hydrogen 1.0079 Y 11 H 2 5 11 ethanol
1 H Hydrogen 1.0079 Y 11 H 4 1 11 ethanol
6 C Carbon 12.0110 Y 2 C 1 1 2 carbon dioxide
6 C Carbon 12.0110 Y 3 C 1 1 3 methane
6 C Carbon 12.0110 Y 4 C 1 2 4 ethane
6 C Carbon 12.0110 Y 5 C 1 3 5 propane
6 C Carbon 12.0110 Y 6 C 1 4 6 butane
6 C Carbon 12.0110 Y 7 C 1 1 7 carbon monoxide
6 C Carbon 12.0110 Y 9 C 2 1 9 magnesium carbonate
6 C Carbon 12.0110 Y 10 C 2 1 10 sodium bicarbonate
6 C Carbon 12.0110 Y 11 C 1 2 11 ethanol
8 O Oxygen 15.9990 Y 1 O 2 1 1 water
8 O Oxygen 15.9990 Y 2 O 2 2 2 carbon dioxide
8 O Oxygen 15.9990 Y 7 O 2 1 7 carbon monoxide
8 O Oxygen 15.9990 Y 9 O 3 3 9 magnesium carbonate
8 O Oxygen 15.9990 Y 10 O 3 3 10 sodium bicarbonate
8 O Oxygen 15.9990 Y 11 O 3 1 11 ethanol
If I understand your question you are having a problem with "TOP". Try using a TOP-N query.
For example:
select *
from (SELECT *
FROM foo
where foo_id=[number]
order by foo_id desc)
where rownum <= 50
This will get you the top fifty results (because I order by desc in the sub query)
Related
I'm trying to make a query and i'm having a bad time with one thing. Suppose I have a table that looks like this:
id
Sample
Species
Quantity
Group
1
1
AA
5
A
2
1
AB
6
A
3
1
AC
10
A
4
1
CD
15
C
5
1
CE
20
C
6
1
DA
13
D
7
1
DB
7
D
8
1
EA
6
E
9
1
EF
4
E
10
1
EB
2
E
In the table I filter to have just 1 sample (but i have many), it has the species, the quantity of that species and a functional group (there are only five groups from A to E). I would like to make a query to group by the samples and make columns of the counts of the species of certain group, something like this:
Sample
N_especies
Group A
Group B
Group C
Group D
Group E
1
10
3
0
2
2
3
So i have to count the species (thats easy) but i don't know how to make the columns of a certain group, can anyone help me?
You can use PIVOT :
Select a.Sample,[A],[B],[C],[D],[E], [B]+[A]+[C]+[D]+[E] N_especies from
(select t.Sample,t.Grp from [WS_Database].[dbo].[test1] t) t
PIVOT (
COUNT(t.Grp)
for t.Grp in ([A],[B],[C],[D],[E])
) a
I have a table T, where I have 4 (integer) columns, A, B, C, and D. There is already a UNIQUE constraint on ABC, but I would need to write a constraint enforcing, that for the same AB combination, the D has the same value, no matter what C is. I.e.
A B C D Note
1 1 1 1 AB is 1,1, D is 1
1 1 2 1
1 1 3 2 wrong! D must be 1, because AB is 1,1
1 1 4 1 ok
2 1 1 5 ok, it's a new AB combination, so a new D value is possible
2 1 2 5 D must be 5 here (and for any following row with AB 2,1)
etc.
I have no idea where to start, and my Google-fu is weak in this case.
SELECT
hg.referencia AS Referencia,
hg.toleInf AS Min,
hg.toleSup AS Max,
ROUND(CAST((hrg.x1+hrg.x2+hrg.x3+hrg.x4)/4 AS FLOAT),2) AS X,
COUNT(hg.Referencia) AS NumGraficos
FROM hRegGeometrias hrg
JOIN hGeometria hg
ON hrg.idGeometria = hg.idGeom
WHERE hrg.idMatriz = 2
GROUP BY hg.referencia, hg.toleInf, hg.toleSup, hrg.x1, hrg.x2, hrg.x3, hrg.x4, hrg.idRegisto
ORDER BY Referencia, IdRegisto ASC
which returns this
what i expect is that it sums the column Referencia but only distinct value, like for example, the sum should be 2 because there's only
'M130342'
'M130344'
So in the column NumGraficos, i would expect the value to be 2.
How to achieve this?
Referencia Min Max X NumGraficos
M130342 2 7 9,81 1
M130342 2 7 9,8 1
M130342 2 7 3,25 1
M130342 2 7 1,75 1
M130342 2 7 3,13 1
M130344 1 7 2 1
M130344 1 7 4,75 1
M130344 1 7 3,25 1
EDIT
It's probably impossible to get the result I expect since this database relations are messed up. I will try a different approach by returning some values separatedly
I have the following table:
pairID source_issue_id destination_issue_id
----------------------------------------------
1 J I
2 B C
3 J M
4 F I
5 A B
6 A E
7 N O
8 J L
9 C D
10 P Q
11 G H
12 B F
13 L K
14 C N
15 A G
16 E F
Representing nodes in a graph.
I'm not using pairID, since does not seem useful.
I want to get the ancestor path for all nodes, the level at which each pair occurs, the full path, and the 'path group'
So far I've used the following code:
;with auxPairs as
(
select
1 as lvl,
b.source_issue_id,
b.destination_issue_id,
cast((b.source_issue_id+ '|' + b.destination_issue_id) as varchar(50)) as "full_path"
from
Pairs2 b
where
b.source_issue_id not in (select destination_issue_id from Pairs2)
union all
select
lvl+1 as lvl,
c.source_issue_id,
c.destination_issue_id,
CAST((a.full_path + '|' + c.destination_issue_id) as varchar(50)) as "full_path"
from
Pairs2 c
join
auxPairs a on a.destination_issue_id = c.source_issue_id
)
That returns the 'connection level' of two nodes (e.g. A|B is level 1) in lvl, the source and destination nodes and the full path (up to that pair), e.g.
lvl source destination full_path
--------------------------------------
1 A B A|B
2 B C A|B|C
3 C N A|B|C|N
4 N O A|B|C|N|O
1 A B A|B
2 B C A|B|C
3 C D A|B|C|D
....
and so on for each path in the tree.
I need to add to this a Path_id or group_id so I get:
path_id lvl source destination full_path
------------------------------------------------
1 1 A B A|B
1 2 B C A|B|C
1 3 C N A|B|C|N
1 4 N O A|B|C|N|O
2 1 A B A|B
2 2 B C A|B|C
2 3 C D A|B|C|D
....
meaning that the nodes with the same path_id are connected in a given order
NOTE: The alphabetical 'fake" order will not work with actual data. I need to use the path_id and lvl to establish the partial order within the path.
I have rank scores of countries for different variables.
I would like to create a column with the maximum rank that occurs per row.
Say the data look something like:
A B C D E F G H I ....
V1 1 4 5 3 12 . 6 9 83
V2 . . 4 6 1 4 7 6 32
So A - X are countries. In rows V1 up you have various variables and in the cells you have the rank score relating to the variable.
Problem is that some countries for whatever reasons don´t score in relation to certain variables, perhaps because V1 is not relevant to country C or whatever.
So in the end I´d like something like
A B C D E F G H I .... newv
V1 1 4 5 3 12 . 6 9 83 83
V2 . . 4 6 1 4 7 6 5 6
I think egen newvar=rowmax(A B C D E F G H I…) does what you need. Have a look at the egen help file for more information. (I presume you need value 7 in the second row, not 6?)