How to use the SQL MINUS keyword - mysql

I am building a social network using asp.net sql, but I am having a problem with using MINUS Operator on SQL. I Select all friend's user data using following keywords
Select * from [UserData]
And i want to reduce following query from that query
SELECT *
FROM [Friendship]
WHERE Friend2 = '" + Session["Email"].ToString() + "'
AND Friend_Status = 1
UNION
SELECT *
FROM [Friendship]
WHERE Friend1 = '" + Session["Email"].ToString() + "'
AND Friend_Status = 1
I tried to it , but when i run this , it gives me details for still this query
Select * from [UserData]
This is the code i tried
SELECT *
FROM [UserData]
MINUS
SELECT *
FROM [Friendship]
WHERE Friend2 = '" + Session["Email"].ToString() + "'
AND Friend_Status = 1
UNION
SELECT *
FROM [Friendship]
WHERE Friend1 = '" + Session["Email"].ToString() + "'
AND Friend_Status = 1
Could you tell me guys how to use this MINUS OPERATOR as i wish?

In Sql Server you can use Except operator which is the equivalent of Minus
EXCEPT returns distinct rows from the left input query that aren’t
output by the right input query.
Query should be like
SELECT *
FROM [UserData]
EXCEPT
SELECT *
FROM (SELECT *
FROM [Friendship]
WHERE Friend2 = '" + Session["Email"].ToString() + "'
AND Friend_Status = 1
UNION
SELECT *
FROM [Friendship]
WHERE Friend1 = '" + Session["Email"].ToString() + "'
AND Friend_Status = 1) a
Note : Make sure you have equal no. of column in Freindship and UserData table

Minus is Oracle syntax.
SQL server equivalent of MINUS is EXCEPT
http://www.sqlservercentral.com/Forums/Topic289916-23-1.aspx

Also good mention that your third code sample runs without errors because MINUS is nothing but a table alias there. In fact it says:
SELECT *
FROM [UserData] AS MINUS;
SELECT *
FROM [Friendship]
...
MINUS is not a language keyword, so for the query compiler it's simply a random string that qualifies as an alias.
If you don't realize this, it can be very confusing to see two queries "connected" by a MINUS simply output two result sets.

Related

Find serial number with one character difference

We have a list of devices with serial numbers, human error has occurred and we have noticed some of them have 1 incorrect character. To find potential matches I've got this query:
Looking for serial 1234
SELECT * FROM tblDevices
WHERE serialNumber LIKE "123_"
OR serialNumber LIKE "12_4"
OR serialNumber LIKE "1_34"
OR serialNumber LIKE "_234"
This works and I can use PHP to incorporate all serial numbers, but this could become a lengthy query with some of the serial numbers containing 40 characters.
It also doesn't resolve if a user enters 2 characters wrong, but at least this narrows it down
I was wondering if there was a neater solution?
Thanks
EDIT
My php solution:
$serial = '123456789101112';
$query = "SELECT * FROM tblDevices WHERE ";
for($i=1; $i<=strlen($serial); $i++){
if ($i > 1){
$query .= " OR ";
}
$query .= "serialNumber LIKE '" . substr_replace($serial, "_", -$i, 1) . "'";
}
Gives me a the query but it's quite lengthy:
SELECT * FROM tblDevices
WHERE serialNumber LIKE '12345678910111_'
OR serialNumber LIKE '1234567891011_2'
OR serialNumber LIKE '123456789101_12'
OR serialNumber LIKE '12345678910_112'
OR serialNumber LIKE '1234567891_1112'
OR serialNumber LIKE '123456789_01112'
OR serialNumber LIKE '12345678_101112'
OR serialNumber LIKE '1234567_9101112'
OR serialNumber LIKE '123456_89101112'
OR serialNumber LIKE '12345_789101112'
OR serialNumber LIKE '1234_6789101112'
OR serialNumber LIKE '123_56789101112'
OR serialNumber LIKE '12_456789101112'
OR serialNumber LIKE '1_3456789101112'
OR serialNumber LIKE '_23456789101112'
In MySQL 8+ you can use a recursive CTE to generate the patterns and then join on them.
WITH RECURSIVE
n
AS
(
SELECT '1234' n
),
p
AS
(
SELECT n.n n,
0 l,
char_length(n.n) - 1 r,
concat('_', right(n.n, char_length(n.n) - 1)) p
FROM n
UNION ALL
SELECT p.n,
p.l + 1 l,
p.r - 1 r,
concat(left(p.n, p.l + 1), '_', right(p.n, p.r - 1)) p
FROM p
WHERE p.r - 1 >= 0
)
SELECT p.p,
d.*
FROM tbldevices d
INNER JOIN p
ON d.serialnumber LIKE p.p;
db<>fiddle

How to convert sql to hql with join and max

I am trying to make this query in hql so i don't have to mapper the query result into my java object , but after trying different options, i still can't make it work. Is it possible to perform this query in hql in any way? The query is:
select t.*
from part_movement t
join
( select id_block_movement, max(start_date) as somedate
from part_movement
where id_area_final_destination = 1
and ((id_area_destination != id_area_final_destination and id_user_receiver is not null) or
(id_area_destination = id_area_final_destination and id_user_receiver is null))
group by id_block_movement
) s
on s.id_block_movement = t.id_block_movement
and s.somedate= t.start_date;
ok i got it finally!! It was: (feels wired answearing myself without having any answear from someone else )
Query q2 = s.createQuery(" from PartMovement t "
+ " WHERE t.areaByIdAreaFinalDestination = ? "
+ " AND t.startDate IN (select max(b.startDate) from PartMovement b "
+ " WHERE ((b.areaByIdAreaDestination != b.areaByIdAreaFinalDestination and b.usersByIdUserReceiver is not null) OR "
+ " (b.areaByIdAreaDestination = b.areaByIdAreaFinalDestination and b.usersByIdUserReceiver is null)) "
+ " group by b.idBlockMovement )");

LIMIT CLAUSE With union

I have this kind of query. I am using limit, but this query gives me 20 results. Can anybody tell me why
SELECT
*,
`tablename`.`bookmark_id` as `bookmark_id`,
`tablename`.`bookmark_date` as `bookmark_date`
FROM ( (" + sql1 + ")
UNION ALL (" + sql2 + ")
UNION ALL (" + sql3 + ") ) AS tablename
WHERE `bookmark_id`
NOT IN
(SELECT `table1`.`bookmark_id`
FROM (
(SELECT `user_bookmarks`.`bookmark_id`
FROM `user_bookmarks`
WHERE `user_bookmarks`.`bookmark_id` = `bookmark_id`
AND `user_id` = 26)
UNION
(SELECT `bookmark_id`
FROM `user_deleted_bookmarks`
WHERE `user_id` = ?)
) AS `table1`)
GROUP BY bookmark_id
ORDER BY `bookmark_date`
DESC limit 17, 20
Thanks
From the SELECT docs
With one argument, the value specifies the number of rows to return from the beginning of the result set:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
I think you want LIMIT 16, 4
When you use limit, second argument is number of results to return.
See : http://dev.mysql.com/doc/refman/5.0/en/select.html
In your case you want :
SELECT .... LIMIT 16,4
You will get 4 rows : 17, 18, 19 and 20.
SELECT *,`tablename`.`bookmark_id` as `bookmark_id`,`tablename`.`bookmark_date` as `bookmark_date` FROM ( (" + sql1 + ") union all (" + sql2 + ") union all (" + sql3 + ") ) AS tablename WHERE `bookmark_id` NOT IN (SELECT `table1`.`bookmark_id` FROM ((SELECT `user_bookmarks`.`bookmark_id` FROM `user_bookmarks` WHERE `user_bookmarks`.`bookmark_id` = `bookmark_id` AND `user_id` = 26) UNION (SELECT `bookmark_id` FROM `user_deleted_bookmarks` WHERE `user_id` = ?)) AS `table1`) GROUP BY bookmark_id ORDER BY `bookmark_date`
DESC limit 16, 4;
for getting result 17,18,19,20
it's count start from 17th position and give next 4 values

how to use limit keyword in oracle

I am retrieving data from table but instead of all row, I want 20 rows at a time for pagination. For this I use limit keyword which work perfectly in Mysql but not in Oracle.
Code:
"select "+ "C.CONTRACTOR_ID,C.CONTRACTOR_NAME,nvl(C.CONTACT_PERSON_1,'-'),nvl(C.CONTACT_PERSON_2,'-'),C.REGISTRATION_NO,CRA.DESCRIPTION REG_AUTH_NAME,"+
"to_char(C.VALID_FROM,'dd/mm/yyyy'),to_char(C.VALID_TO,'dd/mm/yyyy'),CC.DESCRIPTION CONTRACTOR_CLASS,C.INCORP_PLACE,"+
"IT.DESCRIPTION INCORP_TYPE,nvl(to_char(C.DATE_OF_INCORP,'dd/mm/yyyy'),'-') DATE_OF_INCORP,C.ADDRESS1,nvl(C.ADDRESS2,'-'),nvl(C.EMAIL_ID,'-'),"+
"nvl(C.WEBSITE_URL,'-'),nvl(C.PHONE_NO,'-'),nvl(C.FAX_NO,'-'),nvl(C.MOBILE_NO,'-'),C.BANK_NAME,C.BANK_BRANCH,C.ACCOUNT_NO,C.IFSC_CODE," +
"C.PAN_NO,nvl(C.TIN_NO,'-'),nvl(C.CST_NO,'-') "+
"from "+
"CONTRACTOR C "+
"inner join CONTRACTOR_REG_AUTH CRA on CRA.REG_AUTH_ID=C.REG_AUTH_ID "+
"inner join CONTRACTOR_CLASS CC on CC.CLASS_ID=C.CONTRACTOR_CLASS_ID "+
"inner join INCORPORATION_TYPE IT on IT.INCORP_TYPE=C.INCORP_TYPE "+
"limit " + offset + ", " + noOfRecords ";
Here no order by keyword is there. I am retrieving data from different table and then display only 20 rows at a time.
In Oracle, you can use the special rownum variable. This example behaves like limit FirstRow, NrOfRows:
select *
from (
select *
, rownum as rn
from YourTable
order by
id
) as SubQueryAlias
where FirstRow <= rn
and rn < FirstRow + NrOfRows
An optimized version of this query from AskTom, linked from this SO question:
select *
from (
select /*+ FIRST_ROWS(n) */
rownum as rn
, *
from (
select *
from YourTable
order by
id
) as SubQueryAlias1
where rownum <= FirstRow + NrOfRows
) as SubQueryAlias2
where rn >= FirstRow

Oracle MySQL equivalent code

What would be the equivalent Oracle(11g) code for performing following operation:
For MySQL
ps = con.prepareStatement("select SQL_CALC_FOUND_ROWS from student_details where UPPER(name) like UPPER(?) limit " + offset + ", " + noOfRecords);
and rs = ps.executeQuery("SELECT FOUND_ROWS()");
Try it like this:
SELECT *
FROM (select t.*, rownum rn, count(*) over() as SQL_CALC_FOUND_ROWS
from student_details t
where UPPER(name) like UPPER(?))
WHERE rn <= offset
The value returned in "SQL_CALC_FOUND_ROWS" will be the number of records that would have been selected if there wasn't the WHERE rn <= offset clause
The only two RDBMS-specific things I see in your statement are "upper()" and "limit".
Here's a link for using Oracle "rownum" as a workaround for "limit":
https://forums.oracle.com/forums/thread.jspa?threadID=415724.
"Upper()" should work fine as-is in Oracle.