I know that the WHERE ... IN ... clause allows to select all values of a field that exists in a given array. How do I expand this idea to a group of fields? Something like:
SELECT * FROM table_name
WHERE (First, Last) IN ((Adam, Scott), (Betty, Johnson), (Cathy, Wyatt))
Or any other method that allows the same result.
The syntax in the question is valid in some other RDBMSs but not SQL Server. If on 2008+ you can use
SELECT *
FROM table_name t
WHERE EXISTS(SELECT *
FROM (VALUES ('Adam', 'Scott'),
('Betty','Johnson'),
('Cathy','Wyatt')
) v(first, last)
WHERE t.first = v.first AND t.last = f.last
It depends on what you are after really. If you just want to combine 2 fields then you can use something like this:
SELECT * FROM table_name
WHERE First+','+Last IN ('Adam, Scott', 'Betty, Johnson', 'Cathy, Wyatt')
SELECT * FROM Table_name
WHERE First IN ('Adam', 'Betty', 'Cathy')
AND Last IN ('Scott', 'Johnson', 'Wyatt')
Related
I have a table table1 with an nvarchar column column1 that looks something like this:
phrase 1.1;phrase 1.2;phrase 1.3 ...
phrase 2.1;phrase 2.2;phrase 2.3 ...
...
I would like to run an CONTAINS query on only the first phrase in the column. I've tried several variations of this:
SELECT * FROM table1
WHERE CONTAINS(LEFT(table1.column1, CHARINDEX(';', table1.column1) - 1), <search query>)
Is this possible? Ideally, I'd like to do it without creating a new table or column.
Edit -- Some of the errors I'm getting:
Incorrect syntax near the keyword 'LEFT'., An expression of non-boolean type specified in a context where a condition is expected., Incorrect syntax near ";". Expecting '(', or SELECT.
The CONTAINS function is only used when the table (column?) is configured to use full-text indexing. I'm going to guess that this is not the case, here. (Apologies if it is--I have no experience with full-text indexing.)
In any case, as you are matching the first characters in the string, the more precise function LEFT should work fine:
SELECT *
FROM table1
WHERE LEFT(table1.column1, CHARINDEX(';', table1.column1) - 1) = #SearchQuery
Note that you may have problems if there are no semicolons in the string. One way to avoid that would be to guarantee there is always one present, like so:
SELECT *
FROM table1
WHERE LEFT(table1.column1 + ';', CHARINDEX(';', table1.column1) - 1) = #SearchQuery
So there's a couple of problems here. You can only use CONTAINS on a full-text indexed column. If your table is configured that way then great!
Your second issue is that the CONTAINS syntax is a bit clunky, and it doesn't like complexity. You could work around that using a common-table expression, e.g.:
DECLARE #table TABLE (column1 NVARCHAR(100));
INSERT INTO #table SELECT 'phrase 1.1;phrase 1.2;phrase 1.3;'
INSERT INTO #table SELECT 'phrase 2.1;phrase 2.2;phrase 2.3;'
SELECT LEFT(column1, CHARINDEX(';', column1) - 1) FROM #table;
WITH x AS (SELECT LEFT(column1, CHARINDEX(';', column1) - 1) AS search FROM #table)
SELECT * FROM x WHERE CONTAINS(x.search, 'phrase 1.2');
Noting that this won't work, because #table.column1 isn't full-text indexed. But it gets around the syntax error, and could be adapted for your case. Something like this:
WITH x AS (SELECT LEFT(column1, CHARINDEX(';', column1) - 1) AS search FROM table1)
SELECT * FROM x
WHERE CONTAINS(search, <search query>)
If I have a table named dbo.cls_members in SQL server and there is a column named meb_refs containing reference numbers like the following
"A03LV4COOD17JE-SN1AM"
How do I find the records of the DISTINCT first character after the "-" symbol. ?
For example in the reference above the bold "S" after the "-".
Perhaps...
SELECT DISTINCT LEFT(STUFF([Column],1,CHARINDEX('-',[Column]),''),1)
FROM YourTable;
Run the following query:
SELECT DISTINCT
[Letter]
FROM
(
SELECT
column_name [Code] --Step One
,RIGHT(column_name, CHARINDEX('-', REVERSE(column_name))-1) [Part after -]
,LEFT(RIGHT(column_name, CHARINDEX('-', REVERSE(column_name))-1), 1) [Letter]
FROM table_name
) T
It's a simple as:
SELECT DISTINCT SUBSTRING(t.col, CHARINDEX('-',t.col)+1, 1)
FROM <yourtable> t;
Try this:
DECLARE #nar NVARCHAR(max) = 'A03LV4COOD17JE-SN1AM'
SELECT RIGHT(left(REVERSE(#nar), CHARINDEX('-',REVERSE(#nar))-1),1)
Alternatively, you can try:
SELECT * from table
where RIGHT(left(REVERSE(Columnname), CHARINDEX('-',REVERSE(Columnname))-1),1)
in ('S')
i would like to ask you if there is a statement to use calculated fields of the same SELECT-statement:
For example:
Table Test:
Machine Amount Value
500 20 20
SELECT Machine,
Amount*Value AS TestFormula
TestFormula*12 AS TestFormulaYear
FROM Test
What is the correct statement to reuse this calculated field?
Thanks in advance,
Kevin
In sql server at least, you can do it with a subquery:
SELECT Machine
, TestFormula
, TestFormula*12 AS TestFormulaYear
FROM (
SELECT Machine
, Amount*Value AS TestFormula
FROM Test
) T
For the simple example you showed us, I would just recommend repeating the expression
SELECT
Machine,
Amount*Value AS TestFormula,
Amount*Value*12 AS TestFormulaYear
FROM Test;
Other answers have already shown how you can use a subquery to truly reuse the column, but that is not very performant compared to what I wrote above.
You can use a common-table expression (CTE) to reuse the value:
WITH formula AS (
SELECT Machine,
Amount*Value AS TestFormula
FROM Test
)
SELECT Machine,
TestFormula
TestFormula*12 AS TestFormulaYear
FROM formula;
If the batch with the CTE contains multiple statements, the preceding statement must be terminated with a semicolon.
Assuming this is T-SQL:
You can't reference the alias of a column in the SELECT statement, no. If you look at SELECT (Transact-SQL) you'll note that the SELECT is the 8th part of the query to be processed. This means only ORDER BY is going to be able to reference a column's alias.
If you need to do further calculations on a calculated value you need to use a CTE, subquery, or redeclare the calculation. For example:
Repeated calculation:
SELECT [Column] * 10 As Expression,
[Column] * 10 * 5 AS Expression2
FROM [Table];
CTE:
WITH Formula AS(
SELECT [Column] * 10 As Expression
FROM [Table])
SELECT Expression,
Expression * 5 AS Expression2
FROM Formula;
Sub Query:
SELECT Expression,
Expression * 5 AS Expression2
FROM (SELECT [Column] * 10 As Expression
FROM [Table]) Formula;
If you are looking to set up a Statement so that when formulas are changed many columns will be updated, I suppose you could declare the formulas and use Dynamic SQL. There can be an advantage to this if you want to be sure that lots of columns are updated correctly:
Declare #TestFormula as nvarchar(100) = '([Amount]*[Value])'
Declare #TestFormulaYear as nvarchar(100) = '(12*' + #TestFormula + ')'
declare #sql as nvarchar(max)
set #sql = 'SELECT [Machine], ' + #TestFormula + ' AS TestFormula, ' + #TestFormulaYear + ' AS TestFormulaYear
FROM (values(500, 20, 20)) a([Machine], [Amount], [Value])'
exec(#sql)
Is this possible? I am using ORACLE 10g.
For example: I have 50 tables name A01, A02, A03, A04.........A50.
And all these tables have the "SAME COLUMN NAME"
For example: name, age, location
(Note: The Column Names are the same but not the value in the columns).
In the END... I want to view all data from column: name, age, location FROM ALL tables starting with letter A.
(Note 2: All tables starting with letter A are NOT STATIC, they are dynamic meaning different changes could occur. Example: A01 to A10 could be deleted and A99 Could be added).
Sorry for not clarifying.
DECLARE
TYPE CurTyp IS REF CURSOR;
v_cursor CurTyp;
v_record A01%ROWTYPE;
v_stmt_str VARCHAR2(4000);
BEGIN
for rec in (
select table_name
from user_tables
where table_name like 'A%'
) loop
if v_stmt_str is not null then
v_stmt_str := v_stmt_str || ' union all ';
end if;
v_stmt_str := v_stmt_str || 'SELECT * FROM ' || rec.table_name;
end loop;
OPEN v_cursor FOR v_stmt_str;
LOOP
FETCH v_cursor INTO v_record;
EXIT WHEN v_cursor%NOTFOUND;
-- Read values v_record.name, v_record.age, v_record.location
-- Do something with them
END LOOP;
CLOSE v_cursor;
END;
As per my understanding if you want to view all column names of tables starting with A then try below
select column_name,table_name from user_tab_cols where table_name like 'A%';
If your requirement is something else then specify it clearly.
If understand you correctly and the number of tables is constant then you can create a VIEW once
CREATE VIEW vw_all
AS
SELECT name, age, location FROM A01
UNION ALL
SELECT name, age, location FROM A01
UNION ALL
...
SELECT name, age, location FROM A50
UNION ALL
And then use it
SELECT *
FROM vw_all
WHERE age < 35
ORDER BY name
This returns you all tables you need:
select table_name
from user_tables
where table_name like 'A__';
From this, you can build a dynamic sql statement as:
select listagg('select * from '||table_name,' union all ') within group(order by table_name)
from user_tables
where table_name like 'A__'
This returns actually an SQL statement which contains all tables and the unions:
select * from A01 union all select * from A02 union all select * from A03
And finally execute this via native dynamic sql. You can do that in PL/SQL, so you need a function:
create function getA
query varchar2(32000);
begin
select listagg('select * from '||table_name,' union all ') within group(order by table_name)
into query
from user_tables
where table_name like 'A__';
open res for query;
return res;
end;
Note that what you're doing manually is basically called partitioning, and Oracle has a super-great support already available for that out of the box. I.e. you can have something which looks like a super-huge table, but technically it is stored as a set of smaller tables (and smaller indexes), splitted by a partitioning criteria. For example, if you have millions of payment records, you may partition it by year, this way one physical table contains only a reasonable set of data. Still, you can freely select in this, and if you're hitting data from other partitions, Oracle takes care of pulling those in.
I have a select statement where I want to take 100 characters from a field. Is there an easy way to do this?
Here is some pseudo code below.
Select substring(0, 100, longField)
from myTable
You've got it. Use the SUBSTRING() method. This will work on any string/character/binary/image datatypes.
DECLARE #str varchar(1000);
SELECT #str = 'foobar-booz-baz-cowboys';
SELECT SUBSTRING (#str, 0, 10);
-- returns foobar-boo
--from a table:
SELECT SUBSTRING(CustomerName,0,100)
FROM MyTable;
Your pseudocode is pretty close.
select substring(longField, 0, 100)
from myTable
(Just for reference)
SQL Substring::
substring(expression, starting_pos, length)
The easiest way is using LEFT (Transact-SQL):
SELECT
LEFT(longField,100) AS longField, ...
FROM myTable
WHERE...