You have parameters x,y,z stored as key values.
You want to execute an expression z=x+y on those parameters. Expression is stored in another table.
You want to generate an SQL query as simply as possible from the expression.
How can you view those parameter values as a single row with columns (x,y,z) to enable execution of the expression ?
SELECT *
INTO #key_values
FROM
(
SELECT 'x' AS mykey, 2 AS myvalue
UNION ALL
SELECT 'y', 5
UNION ALL
SELECT 'z', 0
) a;
This screams for a PIVOT operator:
;WITH Inputs AS
(
SELECT 'x' AS mykey, 2 AS myvalue
UNION ALL
SELECT 'y', 5
UNION ALL
SELECT 'z', 0
)
SELECT
U.x,
U.y,
U.z,
Result = U.x + U.y
FROM
Inputs AS I
PIVOT (
MAX(I.myvalue) FOR I.mykey IN (x, y, z)
) AS U
Results:
x y z Result
2 5 0 7
You can build any expression you want with the pivoted columns in the SELECT.
If you want to update the z record, you will have to join back to the underlying table since after applying the PIVOT you lose access to original table.
IF OBJECT_ID('tempdb..#Input') IS NOT NULL
DROP TABLE #Input
CREATE TABLE #Input (
mykey VARCHAR(10),
myvalue INT)
INSERT INTO #Input (
mykey,
myvalue)
VALUES
('x', 2),
('y', 5),
('z', 0)
UPDATE I SET
myvalue = R.Result
FROM
#Input AS I
CROSS APPLY (
SELECT
Result = x + y
FROM
#Input AS I
PIVOT (MAX(I.myvalue) FOR I.mykey IN (x, y, z)) AS U
) AS R
WHERE
I.mykey = 'z'
Turn the 3 rows into a single 3 column row using a common table expression and update it to run the expression. So the proposed solution is an updatable cte.
WITH myvalues(x,y,z) AS (
SELECT x.myvalue, y.myvalue, z.myvalue
FROM #key_values AS x
JOIN #key_values AS y ON y.mykey='y' AND x.mykey='x'
JOIN #key_values AS z ON z.mykey='z'
)
UPDATE myvalues SET z=x+y;
SELECT myvalue FROM #key_values WHERE mykey='z';
Related
So i have a union query like:
select count(id)
from table 1
where membernumber = 'x'
and castnumber = 'y'
union
select count(id)
from table 1
where membernumber = 'x'
and castnumber = 'y'
union
etc...
There will be over 200 unions coming from a list 2x 200 table with values for x and y in each row. So each union query has to get the value of x and y from the corresponding row (not in any particular order).
How can i achieve that ?
Thanks
Try this:
DECLARE GLOBAL TEMPORARY TABLE
SESSION.PARAMETERS
(
MEMBERNUMBER INT
, CASTNUMBER INT
) DEFINITION ONLY WITH REPLACE
ON COMMIT PRESERVE ROWS NOT LOGGED;
-- Insert all the the constants in your application with
INSERT INTO SESSION.PARAMETERS
(MEMBERNUMBER, CASTNUMBER)
VALUES (?, ?);
-- I don't know the meaning of the result you want to get
-- but it's equivalent
select distinct count(t.id)
from table1 t
join session.parameters p
on p.membernumber = t.membernumber
and p.castnumber = t.castnumber
group by t.membernumber, t.castnumber;
This is possible:
SELECT 'Bla' AS X
why is this not possible in TeraData:
SELECT 'Bla' AS X
UNION
SELECT 'DiBla' AS X
Is there a way to achieve the above without having to create a temp/volatile/working table in TeraData?
PS:
The error is: A select for a union, intersect or minus must reference a table
If you want two columns on one row, then use:
SELECT 'Bla' AS X, 'DiBla' AS Y
If you want:
X
Bla
DiBla
Then you just do:
select 'Bla' as X
union all
select 'DiBlah' as X;
If you want:
X Y
Bla NULL
NULL DiBla
Then:
SELECT 'Bla' as X, NULL as Y
UNION ALL
SELECT NULL as X, 'DiBla' as Y
You have a attribute name mishmash in your UNION. You can not perform UNION between relations having different structure. Therefore, use
SELECT cast('Bla' as varchar(6)) AS X FROM (SELECT 1 a) t
UNION
SELECT cast('DiBla' as varchar(6)) AS X FROM (SELECT 1 a) t
the explicit casting make sure that the data types are equivalent as well as the attribute names. Another solution could be
SELECT * FROM
(
SELECT cast('Bla' as varchar(6)) AS X
) t
UNION
SELECT * FROM
(
SELECT cast('DiBla' as varchar(6)) AS X
) t
I need to write a write a SQL query that selects values from a table based on several tuples of selection criteria. It could be done using a where clause like this :
where (a = 1 and b='a') or (a=5 and b='s')
Is the best way to select:
select a, pk from x where a in (1,5)
select b, pk from x where b in ('a','s')
and join the result of the two queries using the primary key?
do you mean something(a self join) like this:
select x.a, x.pk
from x
join x x2 on x.pk=x2.pk
where x.a in (1,5)
and x2.b in ('a','s')
?
You can use join on table expression from VALUES. You can add in VALUES as much rows as you want. It will work on MSSQL:
DECLARE #x TABLE ( a INT, b CHAR(1) )
INSERT INTO #x
VALUES ( 1, 'a' ),
( 1, 'b' ),
( 1, 'c' ),
( 2, 'd' ),
( 2, 'e' ),
( 5, 'f' ),
( 5, 's' )
SELECT x.*
FROM #x x
JOIN (
VALUES ( 1, 'a'),
( 5, 's')
) AS v( a, b ) ON x.a = v.a AND x.b = v.b
Output:
a b
1 a
5 s
Based on my understanding you want write a SQL that uses a combination of two filters. Here is a simple solution that will work in any database.
Create a new column say "COLUMN_NEW" in the same table or build a temp table or a view with a new column (plus existing columns from original table).
Insert concatenated values of column a and column b in "COLUMN_NEW". Based on the example mentioned by you values in "COLUMN_NEW" will be "1a" and "5s"
Now you may have a different syntax for concat in different databases. Example concat(a,b) in SQL server.
SQL to select records from the table will be select * from table where COLUMN_NEW in ("1a",5s");
I would like my SQL query to return a row even if there is no row matching in my IN clause.
For exemple this query:
SELECT id, foo
FROM table
WHERE id IN (0, 1, 2, 3)
would return:
id|foo
0|bar
1|bar
2|bar
3|null
But instead I have (because no row with id 3):
id|foo
0|bar
1|bar
2|bar
I have been able to find this trick:
SELECT tmpTable.id, table.bar
FROM (
SELECT 0 as id
UNION SELECT 1
UNION SELECT 2
UNION SELECT 3
) tmpTable
LEFT JOIN
(
SELECT table.foo, table.id
FROM table
WHERE table.id IN (0, 1, 2, 3)
) table
on table.id = tmpTable.id
Is there a better way?
Bonus: How to make it work with myBatis's list variable?
overslacked is right. Most SQL developers use an auxiliary table that stores integers (and one that stores dates). This is outlined in an entire chapter of Joe Celko's "SQL for Smarties".
Example:
CREATE TABLE numeri ( numero INTEGER PRIMARY KEY )
DECLARE #x INTEGER
SET #x = 0
WHILE #x < 1000
BEGIN
INSERT INTO numeri ( numero ) VALUES ( #x )
SET #x = #x + 1
END
SELECT
numero AS id,
foo
FROM
numeri
LEFT OUTER JOIN my_table
ON my_table.id = numero
WHERE
numero BETWEEN 0 AND 3
Main Goal of Programming minimal code high performance no need this things just remove id 3 from in clause
What about just saying:
SELECT id, foo
FROM table
WHERE id >= 0 AND <= 3
I was wondering if this is possible in sqlite.
SELECT * FROM tbl WHERE substr_count(f, '*') = 5
It should return records that have 5 asterisks in the "f" column, like
a*b**c**
****a*
and so on
SELECT * FROM tbl WHERE length(f)-replace(f,'*','') = 5
This solution is easy if you have a tally or numbers table which simply contains a sequential list of integers. This would be a table you populated once but has many uses. With that you have:
Create Table Tally ( N int );
Insert Tally( N )
...
Select Z.<PrimaryKeyCol>, Sum( Z.Val )
From (
Select <PrimaryKeyCol>, 1 As Val
From tbl
Cross Join Tally As T
Where substr( tbl.f, T.N, 1 ) = '*'
) As Z
Group By Z.<PrimaryKeyCol>
Having Sum( Z.Val ) = 5