select
coalesce(x.value,a.default_value) as value
from table1 a
left outer join
(
select
b.configid,
b.value
from table2 b
join table3 c on b.dataid=c.id
where c.id=0
)x on a.id=x.configid
where a.key='abc'
For translating SQL to LINQ,
Translate subselects as separate variables
Translate each clause in LINQ clause order, leaving monadic operators (DISTINCT, TOP, etc) as functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { }) for multiple columns
Left Join is simulated by using a join variable and doing another from from the join variable followed by .DefaultIfEmpty().
Replace coalesce with the conditional operator and a null test.
Related
I created a function that takes a nvarchar and returns a table of one column and variable amount of rows.
The problem is I need to call the funcion like this
SELECT fn_My_Func(V.Value)
FROM tblValues V
How can I call the function for each row in the table and then merge the results in a single resultset?
you can use cross apply
SELECT * FROM tblValues V
CROSS APPLY fn_My_Func(V.Value) L;
The APPLY operator allows you to join two table expressions; the right table expression is processed every time for each row from the left table expression. As you might have guessed, the left table expression is evaluated first and then the right table expression is evaluated against each row of the left table expression for the final result set. The final result set contains all the selected columns from the left table expression followed by all the columns of the right table expression.
SQL Server APPLY operator has two variants; CROSS APPLY and OUTER APPLY
The CROSS APPLY operator returns only those rows from the left table
expression (in its final output) if it matches with the right table
expression. In other words, the right table expression returns rows
for the left table expression match only.
The OUTER APPLY operator returns all the rows from the left table
expression irrespective of its match with the right table expression.
For those rows for which there are no corresponding matches in the
right table expression, it contains NULL values in columns of the
right table expression.
So you might conclude, the CROSS APPLY is equivalent to an INNER JOIN
(or to be more precise its like a CROSS JOIN with a correlated
sub-query) with an implicit join condition of 1=1 whereas the OUTER
APPLY is equivalent to a LEFT OUTER JOIN.
You can use cross apply, but the simplest syntax is:
SELECT mf.*
FROM tblValues V CROSS APPLY
dbo.fn_My_Func(V.Value) mf;
When calling the function, you need to include the schema name.
I am trying to convert a T-SQL query to MS Access SQL and getting a syntax error that I am struggling to find. My MS Access SQL query looks like this:
INSERT INTO IndvRFM_PreSort (CustNum, IndvID, IndvRScore, IndRecency, IndvFreq, IndvMonVal )
SELECT
IndvMast.CustNum, IndvMast.IndvID, IndvMast.IndvRScore,
IndvMast.IndRecency, IndvMast.IndvFreq, IndvMast.IndvMonVal
FROM
IndvMast
INNER JOIN
OHdrMast ON IndvMast.IndvID = OHdrMast.IndvID
INNER JOIN
MyParameterSettings on 1=1].ProdClass
INNER JOIN
[SalesTerritoryFilter_Check all that apply] ON IndvMast.SalesTerr = [SalesTerritoryFilter_Check all that apply].SalesTerr
WHERE
(((OHdrMast.OrdDate) >= [MyParameterSettings].[RFM_StartDate]))
GROUP BY
IndvMast.CustNum, IndvMast.IndvID, IndvMast.IndvRScore,
IndvMast.IndRecency, IndvMast.IndvFreq, IndvMast.IndvMonVal,
[CustTypeFilter_Check all that apply].IncludeInRFM,
[ProductClassFilter_Check all that apply].IncludeInRFM,
[SourceCodeFilter_Check all that apply].IncludeInRFM,
IndvMast.FlgDontUse
I have reviewed differences between MS Access SQL and T-SQL at http://rogersaccessblog.blogspot.com/2013/05/what-are-differences-between-access-sql.html and a few other locations but with no luck.
All help is appreciated.
update: I have removed many lines trying to find the syntax error and I am still getting the same error when running just (which runs fine using T-SQL):
SELECT
IndvMast.CustNum, IndvMast.IndvID, IndvMast.IndvRScore,
IndvMast.IndRecency, IndvMast.IndvFreq, IndvMast.IndvMonVal
FROM
IndvMast
INNER JOIN
OHdrMast ON IndvMast.IndvID = OHdrMast.IndvID
INNER JOIN
[My Parameter Settings] ON 1 = 1
There are a number of items in your query that should also have failed in any SQL-compliant database:
You have fields from tables in GROUP BY not referenced in FROM or JOIN clauses.
Number of fields in SELECT query do not match number of fields in INSERT INTO clause.
The MyParameterSettings table is not properly joined with valid ON expression.
Strictly MS Access SQL items:
For more than one join, MS Access SQL requires paired parentheses but even this can get tricky if some tables are joined together and their paired result joins to outer where you get nested joins.
Expressions like ON 1=1 must be used in WHERE clause and for cross join tables as MyParameterSettings appears to be, use comma-separated tables.
For above reasons and more, it is advised for beginners to this SQL dialect to use the Query Design builder providing table diagrams and links (if you have the MS Access GUI .exe of course). Then, once all tables connect graphically with at least one field selected, jump into SQL view for any nuanced scripting logic.
Below is an adjustment to SQL statement to demonstrate the parentheses pairings and for best practices, uses table aliases especially with long table names.
INSERT INTO IndvRFM_PreSort (CustNum, IndvID, IndvRScore, IndRecency, IndvFreq, IndvMonVal)
SELECT
i.CustNum, i.IndvID, i.IndvRScore, i.IndRecency, i.IndvFreq, i.IndvMonVal
FROM
[MyParameterSettings] p, (IndvMast i
INNER JOIN
OHdrMast o ON i.IndvID = o.IndvID)
INNER JOIN
[SalesTerritoryFilter_Check all that apply] s ON i.SalesTerr = s.SalesTerr
WHERE
(o.OrdDate >= p.[RFM_StartDate])
GROUP BY
i.CustNum, i.IndvID, i.IndvRScore, i.IndRecency, i.IndvFreq, i.IndvMonVal
And in your smaller SQL subset, the last table does not need an ON 1=1 condition and may be redundant as well in SQL Server. Simply a comma separate table will suffice if you intend for cross join. The same is done in above example:
SELECT
IndvMast.CustNum, IndvMast.IndvID, IndvMast.IndvRScore,
IndvMast.IndRecency, IndvMast.IndvFreq, IndvMast.IndvMonVal
FROM
[My Parameter Settings], IndvMast
INNER JOIN
OHdrMast ON IndvMast.IndvID = OHdrMast.IndvID
I suppose there are some errors in your query, the first (more important).
Why do you use HAVING clause to add these conditions?
HAVING (((IndvMast.IndRecency)>(date()-7200))
AND (([CustTypeFilter_Check all that apply].IncludeInRFM)=1)
AND (([ProductClassFilter_Check all that apply].IncludeInRFM)=1)
AND (([SourceCodeFilter_Check all that apply].IncludeInRFM)=1)
AND ((IndvMast.FlgDontUse) Is Null))
HAVING usually used about conditions on aggregate functions (COUNT, SUM, MAX, MIN, AVG), for scalar value you must put in WHERE clause.
The second: You have 12 parenthesis opened and 11 closed in HAVING clause
I would like to know what this statement in SQL actually does:
select *
from table
where A (+)= B
I ran it against:
select *
from table
where A = B
and saw the difference but do not know how to formulate an explanation as to what (+)='s functionality is. It seems to me that (+)= is telling it to make it satisfy the condition A = B where available and ignore/enter as "empty" if components are not available.
Also, this statement is ran within a create view statement.
Thanks in advance.
(+)= is a used to show OUTER JOINS. It is not used now and is deprectaed now(as it is not very much readable). (+) denotes the "optional" table in the JOIN. Also I think that + notation is only present for backwards compatibility because Oracle debuted it before the ANSI standard for joins was put in place.
Also note that Oracle recommends that you use the FROM clause OUTER JOIN syntax rather than the Oracle join operator.
Outer join queries that use the Oracle join operator (+) are subject
to the following rules and restrictions, which do not apply to the
FROM clause OUTER JOIN syntax:
You cannot specify the (+) operator in a query block that also contains FROM clause join syntax.
The (+) operator can appear only in the WHERE clause or, in the context of left-correlation (when specifying the TABLE clause) in the
FROM clause, and can be applied only to a column of a table or view.
If A and B are joined by multiple join conditions, then you must use the (+) operator in all of these conditions. If you do not,
then Oracle Database will return only the rows resulting from a
simple join, but without a warning or error to advise you that you
do not have the results of an outer join.
The (+) operator does not produce an outer join if you specify one table in the outer query and the other table in an inner query.
You cannot use the (+) operator to outer-join a table to itself, although self joins are valid. For example, the following statement
is not valid:
-- The following statement is not valid:
SELECT employee_id, manager_id
FROM employees
WHERE employees.manager_id(+) = employees.employee_id;
However, the following self join is valid:
SELECT e1.employee_id, e1.manager_id, e2.employee_id
FROM employees e1, employees e2
WHERE e1.manager_id(+) = e2.employee_id
ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
The (+) operator can be applied only to a column, not to an arbitrary expression. However, an arbitrary expression can contain
one or more columns marked with the (+) operator.
A WHERE condition containing the (+) operator cannot be combined with another condition using the OR logical operator.
A WHERE condition cannot use the IN comparison condition to compare a column marked with the (+) operator with an expression.
See oracle doc here: http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm
(go down to outer joins)
An outer join extends the result of a simple join. An outer join
returns all rows that satisfy the join condition and also returns some
or all of those rows from one table for which no rows from the other
satisfy the join condition.
Select distinct A.col1, B.col2, col3
from A inner join B on A.id = B.id
and B.id in
(select distinct col2 from B where ..... )
PostgreSQL's plpgsql parser does not like the unqualified "col2" in the parenthetic subquery. Since there's only one table mentioned in the subquery, isn't the parser manufacturing an ambiguity where there is none?
An SQL query like you display would just work.
Since you mention plpgsql, my shot in the dark is that you are only showing fragments from what is actually a plpgsql function and you run into naming conflicts with function parameters, which are visible anywhere in the function body (except dynamic SQL).
No. Outer query columns are available in the subquery too, otherwise you couldn't bind the inner and outer queries together. It's an easy thing to forget and can catch you out if you're not expecting it.
I would like to execute the SQL statement below in VBA code written for MS Access.
I want the integer values of the ID fields to be compared in the JOIN ON criteria.
I get an error when using CInt(). I've also tried Val(), CAST(), and Convert().
Set RecordSet = "SELECT A.id, B.id
FROM A LEFT OUTER JOIN B ON CInt(A.id)=CInt(B.id)"
Lillyana the best would be do the outer join query in MS ACCESS and then go the sql view.
MS ACCESS outer join
Then as for Nz function: It will return string value (custom defined string value) when the value of your columnn is null
Nz
Usual case for the error you are getting is due to,
The SQL statement could not be executed because it contains ambiguous outer joins. To force one of the joins to be performed first, create a separate query that performs the first join and then include that query in your SQL statement. (Error 3258).
Assuming all your id fields are indeed integers, CInt() should work fine. If your numbers are larger, try CLng():
SELECT A.id, B.id
FROM A
INNER JOIN B ON CLng(A.id)=CLng(B.id)