I have a table (a view, actually)
id INTEGER, x1 INTEGER, y1 INTEGER, x2 INTEGER, y2 INTEGER
Now I need to select id of all lines, for which the sum of all values in that row with one given row is below zero,
x1 + y1 + x2 + y2 + x3 + y3 + x4 + y4 < 0
Actually I have more complicated formulae, but it doesn't matter now. I understand that I must create INNER JOIN of this table with itself, but still can't compose the right expression.
I use SQLite + Python, if matters. It is about 100 000 rows in table and a valid result can be from all to none.
If I understand correctly what you're after, than something like this should do it:
SELECT a.id
FROM mytable a
JOIN mytable b ON b.id=some_special_value
WHERE a.x1 + a.x2 + a.y1 + a.y1 + b.x1 + b.x2 + b.y1 + b.y2 < 0
You need to get the next row. Let me assume this is the smallest id greater than the id for a given row. The following calculates the next id using a correlated subquery and then joins in the information for the next row:
select *
from (select t.*,
(select t2.id from t t2 where t2.id > t.id order by t2.id limit 1
) nextId
from t
) t left outer join
t tnext
on t.nextId = tnext.Id
where (t.x1 + t.y1 + t.x2 + t.y2) + (tnext.x1 + tnext.y1 + tnext.x2 + tnext.y2) < 0
You can then access the fields from t and tnext.
If you know that the next row has an id exactly 1 greater than its previous row, then you can simplify this to:
select *
from t left outer join
t tnext
on t.id + 1 = tnext.id
where (t.x1 + t.y1 + t.x2 + t.y2) + (tnext.x1 + tnext.y1 + tnext.x2 + tnext.y2) < 0
Related
I am using SQL Server database and want a way to update MachinesSummary.ShareCount.
Here are my two tables
MachinesSummary
ID Machine1 Machine2 ShareCount
-------------------------------
1 A J NULL
2 K S NULL
3 A E NULL
4 J A NULL
5 Y U NULL
6 S W NULL
7 G A NULL
8 W S NULL
The other table is MachineDetails
ProcessNo Machine
------------------
1 A
1 H
1 W
2 A
2 J
2 W
3 Y
3 K
4 J
4 A
I want to update ShareCount in the MachineSummary table with the count of processes that both Machine1 and Machine2 share.
For record 1 in the MachineSummary table, I want the number of processes both share in MachineDetails which is 1 in this case
While for record 4 the ShareCount is 2
I tried this
UPDATE M
SET ShareCount = COUNT(DISTINCT X.ProcessNo)
FROM
(SELECT ProcessNo, ',' + STRING_AGG(Machine,',') + ',' Machines
FROM MachineDetails
GROUP BY ProcessNo) X
INNER JOIN MachinesSummary M ON X.Machines LIKE '%'+ M.Machine1 + '%'
AND X.Machines LIKE '%'+ M.Machine2 + '%'
But I wonder if there is an easier high performance way
The MachineDetails table has 250 million rows.
Well, I would use a self-join to get the number of combinations:
UPDATE M
SET ShareCount = num_processes
FROM MachinesSummary M JOIN
(SELECT md1.Machine as machine1, md2.Machine as machine2, COUNT(*) as num_processes
FROM MachineDetails md1 JOIN
MachinesDetails md2
ON md1.processno = md2.processno
GROUP BY md1.Machine, md2.Machine
) md
ON md.Machine1 = M.machine1 AND md.Machine2 = M.machine2;
I would use an updatable CTE here:
WITH cte AS (
SELECT Machine, COUNT(*) AS cnt
FROM MachineDetails
GROUP BY Machine
),
cte2 AS (
SELECT ShareCount, COALESCE(t1.cnt, 0) AS m1_cnt, COALESCE(t2.cnt, 0) AS m2_cnt
FROM MachineSummary ms
LEFT JOIN cte t1 ON t1.Machine1 = ms.Machine
LEFT JOIN cte t2 ON t2.Machine2 = ms.Machine
)
UPDATE cte2
SET ShareCount = m1_cnt + m2_cnt;
The logic of the first CTE involving the MachineDetails table is to get the counts for every machine. The second CTE joins this counts CTE to the MachineSummary table twice, once for each of machine 1 and 2. Then, we update this second CTE and assign the sum of counts.
Suppose I have total 800 eligible rows in database which is ordered by a column requisitionid in descending order. I want to display the records in 80 pages each page having 10 rows. We are using requisitionid as seek predicate. So the predicate should be less than or greater than? As the query will progress from UI (Angular + primeNG), I want to send just one parameter - requisitionid. If it is less than query, then the query will be SELECT ... FROM ... where requisitionid < ?, so here we are talking about first row. If we go for greater than query i.e. SELECT ... FROM ... where requisitionid > ?, here we are talking about last row of the page.
Please refer to Life without offset
EDIT
Actual code:
with topten as (SELECT DISTINCT TOP 10
REQN.CASE_ID
,userContact2.BV_First_Name + ' ' + userContact2.BV_Last_Name ReQCreater
,REQN.BV_Internal_Job_Title
,REQN.BV_Posted_Job_Title as postedJobTitle
,REQN.BV_Status
,REQN.BV_Taleo_Id
,REQN.BV_WD_PositionID
,jobcode.BV_Job_Code
,loc.BV_LocationCode
,loc.BV_LocationName
,D.BV_Division_Code AS 'divCode',
ISNULL(loc.BV_Address1,'') + CASE WHEN ISNULL(loc.BV_Address1,'') = '' THEN '' ELSE ', ' END + ISNULL(loc.BV_Address2,'') + CASE WHEN ISNULL(loc.BV_Address2,'') = '' THEN '' ELSE ', ' END
+ ISNULL(loc.BV_City,'') + CASE WHEN ISNULL(loc.BV_City,'') = '' THEN '' ELSE ', ' END + ISNULL(loc.BV_State,'') + CASE WHEN ISNULL(loc.BV_State,'') = '' THEN '' ELSE (case when ISNULL(loc.BV_ZipCode,'') = '' THEN '' ELSE ', ' END) END
+ ISNULL(loc.BV_ZipCode,'') AS locationAddress
from dbo.CW_V_REQN as REQN
INNER JOIN dbo.CW_TL_Requisition__Location_Master as reqLocLink on REQN.CASE_ID = reqLocLink.FROM_ID
INNER JOIN dbo.CW_V_LOCTMAST as loc on loc.CASE_ID = reqLocLink.TO_ID
INNER JOIN dbo.CW_TL_UserContactInfo__Location_Master as locUserLink on locUserLink.TO_ID = loc.CASE_ID
INNER JOIN dbo.CW_V_USERCONT as userContact on userContact.CASE_ID = locUserLink.FROM_ID
LEFT JOIN dbo.CW_TL_Requisition__Department as reqDeptLink on REQN.CASE_ID = reqDeptLink.FROM_ID
INNER JOIN dbo.CW_V_DEPARTME as dept on dept.CASE_ID = reqDeptLink.TO_ID
LEFT JOIN dbo.CW_TL_UserContactInfo__Department_Master as deptUserLink on dept.CASE_ID=deptUserLink.TO_ID
INNER JOIN dbo.CW_TL_Requisition__Job_Code as reqJobLink on REQN.CASE_ID = reqJobLink.FROM_ID
LEFT JOIN dbo.CW_V_JOBCODE as jobcode on jobcode.CASE_ID = reqJobLink.TO_ID
LEFT JOIN dbo.CW_V_USERCONT as userContact2 on (userContact2.BV_Login_Name = REQN.CREATED_BY)
LEFT JOIN CW_TL_LocationMaster__Division_Master LD ON (LD.FROM_ID = loc.CASE_ID)
LEFT JOIN CW_V_DIVISION D ON (D.CASE_ID = LD.TO_ID)
WHERE userContact.BV_Login_Name = #LOGINNAME
AND REQN.CASE_ID < #MINCASEIDPREVPAGE
ORDER BY REQN.CASE_ID DESC
)
select topten.*
, T.*
from topten
cross join (select min(case_id) as min from topten) as T
For key based pagination on a descending key, the WHERE clause predicate should be < for the next page and > for the previous page. Also, the ORDER BY clause for the previous page needs to be ASC (for the TOP predicate) along an outer DESC (for the descending key display sequence). Below is an example.
--create test table with sample data
CREATE TABLE dbo.YourTable(
requisitionid int PRIMARY KEY
);
WITH
t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
,t1000 AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS num FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c)
INSERT INTO dbo.YourTable WITH(TABLOCKX)
SELECT num
FROM t1000
WHERE num <= 800;
GO
--query for first page (page 1) on descending key (returns 800-791)
SELECT TOP(10) requisitionid
FROM YourTable
ORDER BY requisitionid DESC;
GO
--query for next page (page 2) on descending key (returns 790-781)
DECLARE #LastRequisitionIdOnPage int = 791;
SELECT TOP(10) requisitionid
FROM YourTable
WHERE requisitionid < #LastRequisitionIdOnPage
ORDER BY requisitionid DESC;
GO
--query for previous page (page 1) on descending key (returns 800-791)
DECLARE #FirstRequisitionIdOnPage int = 790;
SELECT requisitionid
FROM (
SELECT TOP(10) requisitionid
FROM YourTable
WHERE requisitionid > #FirstRequisitionIdOnPage
ORDER BY requisitionid ASC
) AS prev_page
ORDER BY requisitionid DESC;;
GO
If I understand your question, you should be able to use the follow clause at the end of your SELECT query:
OFFSET (#Page * 10) ROWS FETCH NEXT 10 ROWS ONLY
If this is not what you are looking for, please post your current query so we can see what you are doing now.
In MS Access I am trying to update 1 table based on a concatenation of columns NOT matching a concatenation of columns in another table. Here is what I need to do.
If ((Table1.A + Table1.B + Table1.C + Table1.D)
NOT EQUAL TO (Table2.E + Table2.F + Table2.G + Table2.H))
Then set Table1.error = x
I know this is some type of SQL join but I'm struggling with it.
Update:
Ok, I finally got something to work. This is what I have:
SELECT [Table1].[A] & [Table1].[B] & [Table1].[C] & [Table1].[D] AS Expr1
FROM Table1, Table2
WHERE ((([Table2].[E] & [Table2].[F] & [Table2].[G] & [Table2].[H])<>
[Table1].[A] & [Table1].[B] & [Table1].[C] & [Table1].[D]));
That'll run but it shows me every unmatched line. I need to search table 1 for any rows that don't exist in table 2 and only return those unmatched rows in table 1.
UPDATE (SELECT Table1.error
FROM Table1,
Table2
WHERE ((Table1.A + Table1.B + Table1.C + Table1.D)
NOT EQUAL TO (Table2.E + Table2.F + Table2.G + Table2.H)))
SET Table1.error = x
You could try an update join with on clause for the <> results
update T
set t.error = x
FROM Table1 AS T
INNER JOIN (
SELECT Table2.E + Table2.F + Table2.G + Table2.H as T2_RESULT
from Table2
) AS ON T2.T2_RESULT <> (Table1.A + Table1.B + Table1.C + Table1.D)
UPDATE Table1 AS T1
INNER JOIN Table2 AS T2
ON (Table1.A + Table1.B + Table1.C + Table1.D) NOT EQUAL TO (Table2.E + Table2.F + Table2.G + Table2.H))
set T1.error = x
It will update Table1.error with inner join Table2 on condition of columns' sum not equal.
Assuming field [E] in Table 2 can never be null, you can find your UNMATCHED Table 1 records by searching for Nulls after a Left Join:
SELECT [T1].[A] & [T1].[B] & [T1].[C] & [T1].[D] AS Concat1
FROM
[Table1] as T1
Left Join [Table2] as T2 ON
((([T2].[E] & [T2].[F] & [T2].[G] & [T2].[H]) = [T1].[A] & [T1].[B] & [T1].[C] & [T1].[D]))
WHERE
[T2].[E] is NULL;
This will return All your Table 1 records that don't have a matching Table 2 record.
You can call that query into your update.
I realized that the fields didn't need to be concatenated (they were concatenated in previous code so I assumed it was for a reason). So I did an unmatched query wizard with the 4 fields separately within the same query.
When I run the query below
SELECT
COUNT(COALESCE(CASE PARTPPHY.TITRE
WHEN 1 THEN 'Monsieur '
WHEN 2 THEN 'Madame '
WHEN 3 THEN 'Madame '
ELSE ''
END + PARTPPHY.IDENTITE, PARTPPHY.IDENTITE)) AS ident,
RESPONSABLES.DIR_LOC,
PARTPPHY.IU_PART_PP,
COALESCE(CASE PARTPPHY.TITRE
WHEN 1 THEN 'Monsieur '
WHEN 2 THEN 'Madame '
WHEN 3 THEN 'Madame '
ELSE ''
END + PARTPPHY.IDENTITE,PARTPPHY.IDENTITE) AS IDENTITE,
FONCTIONS_ECO.LIBEL AS LIBEL_FONCTION
FROM
RESPONSABLES
INNER JOIN
ETABLISSEMENTS ON ETABLISSEMENTS.IU_ETS = RESPONSABLES.IU_ETS
LEFT OUTER JOIN
PARTPPHY ON RESPONSABLES.IU_PART_PP = PARTPPHY.IU_PART_PP
LEFT OUTER JOIN
FONCTIONS_ECO ON FONCTIONS_ECO.IU_FONC_ECO = RESPONSABLES.IU_FONC
WHERE
ETABLISSEMENTS.IU_ETS = 14783
AND RESPONSABLES.GESTDEL = 1
GROUP BY
RESPONSABLES.DIR_LOC,
PARTPPHY.IU_PART_PP,
COALESCE(CASE PARTPPHY.TITRE WHEN 1 THEN 'Monsieur ' WHEN 2 THEN 'Madame ' WHEN 3 THEN 'Madame ' ELSE '' END + PARTPPHY.IDENTITE,PARTPPHY.IDENTITE),
FONCTIONS_ECO.LIBEL
This is my result
Yet when I'm using this query
SELECT COUNT(COALESCE(CASE PARTPPHY.TITRE
WHEN 1 THEN 'Monsieur '
WHEN 2 THEN 'Madame '
WHEN 3 THEN 'Madame '
ELSE '' END + PARTPPHY.IDENTITE,PARTPPHY.IDENTITE)) AS ident,
RESPONSABLES.DIR_LOC,
PARTPPHY.IU_PART_PP,
COALESCE(CASE PARTPPHY.TITRE WHEN 1 THEN 'Monsieur ' WHEN 2 THEN 'Madame ' WHEN 3 THEN 'Madame ' ELSE '' END + PARTPPHY.IDENTITE,PARTPPHY.IDENTITE) AS IDENTITE,
FONCTIONS_ECO.LIBEL AS LIBEL_FONCTION
FROM RESPONSABLES
INNER JOIN ETABLISSEMENTS ON ETABLISSEMENTS.IU_ETS = RESPONSABLES.IU_ETS
LEFT OUTER JOIN PARTPPHY ON RESPONSABLES.IU_PART_PP = PARTPPHY.IU_PART_PP
LEFT OUTER JOIN FONCTIONS_ECO ON FONCTIONS_ECO.IU_FONC_ECO = RESPONSABLES.IU_FONC
WHERE ETABLISSEMENTS.IU_ETS = 1
AND RESPONSABLES.GESTDEL = 1
GROUP BY RESPONSABLES.DIR_LOC,
PARTPPHY.IU_PART_PP,
COALESCE(CASE PARTPPHY.TITRE WHEN 1 THEN 'Monsieur ' WHEN 2 THEN 'Madame ' WHEN 3 THEN 'Madame ' ELSE '' END + PARTPPHY.IDENTITE,PARTPPHY.IDENTITE),
FONCTIONS_ECO.LIBEL
I have this
My questions are the following:
It does not seem to be a null nor an empty space: What is it?
I want to have a value in my count: What should I do to have this?
Thanks
While using a COUNT without a GROUP BY clause you will always return a row, even if the WHERE clause is not equal to any of the records in your table. But while using a GROUP BY clause , it will return the records only if the WHERE clause condition is true.
Please check the following test scripts
DECLARE #TEST TABLE(ID INT)
INSERT INTO #TEST VALUES(10)
--1.
SELECT COUNT(*) FROM #TEST WHERE ID = 11 --Result is 0
--2.
SELECT COUNT(*),ID FROM #TEST WHERE ID = 11 GROUP BY ID --No Result
Here the first query always return a result
(No column name)
0
But second query not.
You can modify your second query something like the below script to get a '0' result
SELECT ISNULL(( SELECT COUNT(*) FROM #TEST WHERE ID = 11 GROUP BY ID ),0)
There is one more valid option. In both cases you are using the INNER JOIN, which is exclusive join meaning, if the join condition is not satisfied then no data is return, or more precise your result is an empty set.
Your INNER JOIN condition is on ETABLISSEMENTS.IU_ETS = RESPONSABLES.IU_ETS
In the first query your where statement says
WHERE ETABLISSEMENTS.IU_ETS = 14783 AND RESPONSABLES.GESTDEL = 1
This is where you have an empty data set
And in the second query your where statement is
WHERE ETABLISSEMENTS.IU_ETS = 1 AND RESPONSABLES.GESTDEL = 1
So to answer your first query:
Possibly there is no matching record, which has the ETABLISSEMENTS.IU_ETS = 14783 AND RESPONSABLES.GESTDEL = 1 therefore we are getting an empty set
In the second case the where statement is satisfied and there is a corresponding entry in both tables therefore we have a result.
Depending which side of the Join you are interested in, i.e. in which table yo will expect the row to be present you can switch the
JOIN to OUTER JOIN (LEFT or RIGHT)
The outer join is inclusive, meaning that it will return all rows from the table left or right to the join even if there is no record in corresponding table.
Then apply count on the corresponding table, i.e. id column. If there is no record then you will get 0
Example to illustrate
CREATE TABLE #Left
(
id INT
,col1 CHAR(3)
)
CREATE TABLE #Right
(
id INT
,col2 CHAR(3)
)
INSERT INTO #Right
( id, col2)
VALUES
(1,'c1')
,(2,'c2')
,(3,'c4')
,(4,'c5')
INSERT INTO #Left
( id, col1)
VALUES
(1,'c1')
,(2,'c2')
,(3,'c3')
,(4,'c5')
-- empty set
SELECT
*
FROM #Left L
INNER JOIN #Right R
ON L.col1 = R.col2
WHERE col1 = 'c3'
-- matching rows
SELECT
*
FROM #Left L
INNER JOIN #Right R
ON L.col1 = R.col2
WHERE col1 = 'c2'
-- Left Join
SELECT
L.*
,COUNT(R.col2)
FROM #Left L
LEFT JOIN #Right R
ON L.col1 = R.col2
WHERE col1 = 'c3'
GROUP BY L.id, L.col1
I am searching for this question since last 2 days what is the difference between UNION and JOIN. Specifically UNION ALL and Natural JOIN.
So I have 2 queries here
first one is
CREATE OR REPLACE VIEW VU_m1 AS
SELECT department_id,manager_id FROM employees
NATURAL JOIN departments ;
SELECT * FROM vu_m1;
and the second one is
CREATE OR REPLACE VIEW VU_m2 AS
SELECT department_id,manager_id FROM employees
UNION ALL
SELECT department_id,manager_id FROM departments;
SELECT * FROM vu_m2;
The result from both the query is exactly same.
So now what is the difference between UNION ALL and Natural JOIN
Details:
I am using Oracle 11gR2 working on Sample HR database.
This is my 2 cents
+----------------------------------+--------------------------------------------+
+- UNION +- JOIN +
+----------------------------------+--------------------------------------------+
+SELECT 1 AS bah FROM DUAL + SELECT * +
+ EMP.DEPTNO + FROM +
+SELECT 2 AS bah FROM DUAL; + (SELECT 1 AS bah from dual) foo +
+ + JOIN +
+ + (SELECT 2 AS bah from dual) bar +
+ + ON 1=1; +
+----------------------------------+--------------------------------------------+
+- RESULTS +
+----------------------------------+--------------------------------------------+
+This gives everything in vertical + This gives everything in horizontal +
+ BAH + BAH BAH +
+ 1 + 1 2 +
+ 2 + +
+----------------------------------+--------------------------------------------+
+- OBSERVATIONS +
+----------------------------------+--------------------------------------------+
+ UNION puts lines from queries + JOIN makes a Cartesian product +
+ after each other + and subsets it +
+ + +
+ UNION combines the results of + JOIN can retrieve data from two or +
+ two or more queries into a single+ more tables based on logical relationships +
+ result set that includes all the + between the tables. Joins indicate how SQL +
+ rows that belong to all queries + should use data from one table to select +
+ in the union. + the rows in another table. +
+ + +
+ UNION makes two queries look + JOIN examine two or more tables in +
+ like one. + a single query statement +
+ + +
+ UNION returns the results of two + JOIN relates similar data in different +
+ different queries as a single + tables. +
+ recordset. + +
+ + +
+----------------------------------+--------------------------------------------+
JOIN picks fields from table A and fields from table B and put all of them together, JOIN is "horizontal" for example:
SELECT A.A1, A.A2, A.A3, B.B1, B.B2
FROM A
INNER JOIN B
ON A.A10 = B.B20
which can be written also like:
select A1, A2, A3, B1, B2 from TABLEA, TABLEB
WHERE A10 = B20
result:
Field-A1 | Field-A2 | Field-A3 | Field-B1 | Field-B2 |
...
UNION/UNIONALL:
Difference between the two is that UNION returns only distinct results while UNIONALL returns ALL the results (including duplicates). UNION/UNIONALL combines the results of two selects - but there's a "catch" - the column-names must be exactly the same - this property make UNION "vertical", for example:
Select A1 as X1, A2 as X2 from TABLEA
UNIONALL
Select B1 as X1, B2 as X2 from TABLEB
result:
Field-X1 | Field-X2
A1 | A2
B1 | B2
...
join:
A join is an SQL operation performed to establish a connection between two or more database tables based on matching columns, thereby creating a relationship between the tables. Most complex queries in an SQL database management system involve join commands.
e.g:
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
The UNION operator is used to combine the result-set of two or more SELECT statements.
Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types. Also, the columns in each SELECT statement must be in the same order
syntax:
SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;