Using UNION to concatenate query results - mysql
I'm trying to execute queries and append the results into another query result, to maintain order. So I calculating the distance and at the end ordering by a "fake var" and then by distance.
Here's the query:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `Test`(IN basic_user_id INT, IN max_dist INT, IN q VARCHAR(255), IN index_start INT, IN index_end INT)
BEGIN
DECLARE mylon DOUBLE;
DECLARE mylat DOUBLE;
DECLARE lon1 FLOAT;
DECLARE lon2 FLOAT;
DECLARE lat1 FLOAT;
DECLARE lat2 FLOAT;
SET #location_id = (SELECT location_id from basicuser where id = basic_user_id);
SET #group_id = (SELECT group_id from basicuser where id = basic_user_id);
SET #subgroup_id = (SELECT subgroup_id from basicuser where id = basic_user_id);
SET #tertiarygroup_id = (SELECT tertiarygroup_id from basicuser where id = basic_user_id);
-- get the original lon and lat for the userid
SELECT longitude, latitude into mylon, mylat from location where id = #location_id;
set lon1 = mylon - max_dist / abs(cos(radians(mylat)) * 69);
set lon2 = mylon + max_dist / abs(cos(radians(mylat)) * 69);
set lat1 = mylat - (max_dist / 69);
set lat2 = mylat + (max_dist / 69);
select #group_id, #subgroup_id, #tertiarygroup_id;
(
SELECT 1 as `temp`, `inradar_ad`.*, 3956 * 2 * ASIN(SQRT(POWER(SIN((orig.latitude - dest.latitude) * pi()/180 / 2), 2) + COS(orig.latitude * pi()/180) * COS(dest.latitude * pi()/180) * POWER(SIN((orig.longitude - dest.longitude) * pi()/180 / 2), 2))) as distance
FROM
location AS dest
LEFT OUTER JOIN `inradar_ad` ON (`inradar_ad`.location_id = dest.id)
LEFT OUTER JOIN `inradar_ad_company` ON (`inradar_ad`.`id` = `inradar_ad_company`.`inradarad_ptr_id`)
LEFT OUTER JOIN `inradar_ad_person` ON (`inradar_ad`.`id` = `inradar_ad_person`.`inradarad_ptr_id`)
LEFT OUTER JOIN `inradar_category` ON (`inradar_ad`.`category_id` = `inradar_category`.`id`)
LEFT OUTER JOIN `inradar_subcategory` ON (`inradar_ad`.`subcategory_id` = `inradar_subcategory`.`id`)
LEFT OUTER JOIN `basicuser` ON (`inradar_ad`.`owner_id` = `basicuser`.`id`)
LEFT OUTER JOIN `auth_user` ON (`basicuser`.`user_id` = `auth_user`.`id`)
LEFT OUTER JOIN `inradar_ad_multiple` ON (`inradar_ad`.`multiple_advertiser_id` = `inradar_ad_multiple`.`id`),
location AS orig
WHERE orig.id = #location_id AND
(
(
`inradar_ad_multiple`.`id` IS NULL AND
(
`inradar_ad_company`.`corporate_name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_ad_person`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_category`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_subcategory`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_ad`.`description` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`auth_user`.`first_name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`auth_user`.`last_name` LIKE REPLACE('%$$**$$%', '$$**$$', q)
)
)
) AND
`basicuser`.`tertiarygroup_id` = #tertiarygroup_id AND
dest.longitude BETWEEN lon1 AND lon2 AND dest.latitude BETWEEN lat1 AND lat2
HAVING distance < max_dist
) UNION (
SELECT 2 as `temp`, `inradar_ad`.*, 3956 * 2 * ASIN(SQRT(POWER(SIN((orig.latitude - dest.latitude) * pi()/180 / 2), 2) + COS(orig.latitude * pi()/180) * COS(dest.latitude * pi()/180) * POWER(SIN((orig.longitude - dest.longitude) * pi()/180 / 2), 2))) as distance
FROM
location AS dest
LEFT OUTER JOIN `inradar_ad` ON (`inradar_ad`.location_id = dest.id)
LEFT OUTER JOIN `inradar_ad_company` ON (`inradar_ad`.`id` = `inradar_ad_company`.`inradarad_ptr_id`)
LEFT OUTER JOIN `inradar_ad_person` ON (`inradar_ad`.`id` = `inradar_ad_person`.`inradarad_ptr_id`)
LEFT OUTER JOIN `inradar_category` ON (`inradar_ad`.`category_id` = `inradar_category`.`id`)
LEFT OUTER JOIN `inradar_subcategory` ON (`inradar_ad`.`subcategory_id` = `inradar_subcategory`.`id`)
LEFT OUTER JOIN `basicuser` ON (`inradar_ad`.`owner_id` = `basicuser`.`id`)
LEFT OUTER JOIN `auth_user` ON (`basicuser`.`user_id` = `auth_user`.`id`)
LEFT OUTER JOIN `inradar_ad_multiple` ON (`inradar_ad`.`multiple_advertiser_id` = `inradar_ad_multiple`.`id`),
location AS orig
WHERE orig.id = #location_id AND
(
(
`inradar_ad_multiple`.`id` IS NULL AND
(
`inradar_ad_company`.`corporate_name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_ad_person`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_category`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_subcategory`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_ad`.`description` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`auth_user`.`first_name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`auth_user`.`last_name` LIKE REPLACE('%$$**$$%', '$$**$$', q)
)
)
) AND
`basicuser`.`subgroup_id` = #subgroup_id AND
dest.longitude BETWEEN lon1 AND lon2 AND dest.latitude BETWEEN lat1 AND lat2
HAVING distance < max_dist
) UNION (
SELECT 3 as `temp`, `inradar_ad`.*, 3956 * 2 * ASIN(SQRT(POWER(SIN((orig.latitude - dest.latitude) * pi()/180 / 2), 2) + COS(orig.latitude * pi()/180) * COS(dest.latitude * pi()/180) * POWER(SIN((orig.longitude - dest.longitude) * pi()/180 / 2), 2))) as distance
FROM
location AS dest
LEFT OUTER JOIN `inradar_ad` ON (`inradar_ad`.location_id = dest.id)
LEFT OUTER JOIN `inradar_ad_company` ON (`inradar_ad`.`id` = `inradar_ad_company`.`inradarad_ptr_id`)
LEFT OUTER JOIN `inradar_ad_person` ON (`inradar_ad`.`id` = `inradar_ad_person`.`inradarad_ptr_id`)
LEFT OUTER JOIN `inradar_category` ON (`inradar_ad`.`category_id` = `inradar_category`.`id`)
LEFT OUTER JOIN `inradar_subcategory` ON (`inradar_ad`.`subcategory_id` = `inradar_subcategory`.`id`)
LEFT OUTER JOIN `basicuser` ON (`inradar_ad`.`owner_id` = `basicuser`.`id`)
LEFT OUTER JOIN `auth_user` ON (`basicuser`.`user_id` = `auth_user`.`id`)
LEFT OUTER JOIN `inradar_ad_multiple` ON (`inradar_ad`.`multiple_advertiser_id` = `inradar_ad_multiple`.`id`),
location AS orig
WHERE orig.id = #location_id AND
(
(
`inradar_ad_multiple`.`id` IS NULL AND
(
`inradar_ad_company`.`corporate_name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_ad_person`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_category`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_subcategory`.`name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`inradar_ad`.`description` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`auth_user`.`first_name` LIKE REPLACE('%$$**$$%', '$$**$$', q) OR
`auth_user`.`last_name` LIKE REPLACE('%$$**$$%', '$$**$$', q)
)
)
) AND
`basicuser`.`group_id` = #group_id AND
dest.longitude BETWEEN lon1 AND lon2 AND dest.latitude BETWEEN lat1 AND lat2
HAVING distance < max_dist
)
ORDER by `temp` ASC, distance ASC;
END
But that returns duplicated entries, like this:
# temp, id, seller_id, owner_id, description, category_id, subcategory_id, video_url, logo, location_id, business_hours, subscription_plan_id, tags, advertiser_occupation, advertiser_group_message, email, email_contact_form, website, e_commerce, phone, phone2, blap_phone, delivery, comment_votes, comment_quantity, multiple_advertiser_id, user_type, additional_info, advertiser_available, used_free_coupom, distance
1 37294 40 35 2 37667 (62) 3523-9609 0 0 company 0 0 105.60177674937776
1 37256 36 35 1 37557 (19)4141-5857 0 0 0 company 0 0 233.5020148948106
1 37254 40 35 1 37555 (16) 3624-8409 0 0 company 0 0 297.9775326093067
1 37264 40 35 1 37579 (67) 3251-1186 0 0 company 0 0 829.305941965672
2 37294 40 35 2 37667 (62) 3523-9609 0 0 company 0 0 105.60177674937776
2 37255 52 35 1 37556 (11) 5669-0169 0 0 company 0 0 218.0241298958371
2 37256 36 35 1 37557 (19)4141-5857 0 0 0 company 0 0 233.5020148948106
2 37254 40 35 1 37555 (16) 3624-8409 0 0 company 0 0 297.9775326093067
2 37264 40 35 1 37579 (67) 3251-1186 0 0 company 0 0 829.305941965672
3 37294 40 35 2 37667 (62) 3523-9609 0 0 company 0 0 105.60177674937776
3 37255 52 35 1 37556 (11) 5669-0169 0 0 company 0 0 218.0241298958371
3 37256 36 35 1 37557 (19)4141-5857 0 0 0 company 0 0 233.5020148948106
3 37254 40 35 1 37555 (16) 3624-8409 0 0 company 0 0 297.9775326093067
3 37264 40 35 1 37579 (67) 3251-1186
0 0 company 0 0 829.305941965672
What am I doing wrong, there?
Thanks very much in advance.
You can get rid of the UNION and do the whole thing in one SELECT.
CASE statement
Select everything you want and set your fake var within the SELECT clause.
SELECT CASE
WHEN `basicuser`.`tertiarygroup_id` = #tertiarygroup_id THEN 1
WHEN `basicuser`.`subgroup_id` = #subgroup_id THEN 2
WHEN `basicuser`.`group_id` = #group_id THEN 3
END as temp, ...
...
WHERE (
`basicuser`.`tertiarygroup_id` = #tertiarygroup_id OR
`basicuser`.`subgroup_id` = #subgroup_id OR
`basicuser`.`group_id` = #group_id
) AND ...
ORDER BY booleans
If you have a tree-like structure for your tertiary/secondary/groups, you can leverage the boolean order in the ORDER BY clause
ORDER BY cond1 DESC, cond2 DESC, cond3 DESC, distance ASC
Related
Subset a table such that the samples are normally distributed around a value in a column
I have the following table called original_table: name height age personA 180 21 personB 190 37 personC 168 27 personD 182 56 ... My goal is to create two random samples of size 100 from the original_table such that the mean of age is normally distributed around 25, and height average is close to 175. Basically, a person with age 25 and height 175 has the highest chance of being in the tables, but not guaranteed.
The trick is to find the normal distribution function from other languages, and then convert it to mysql syntax. For example, convert from the following java code to mysql //java.util.Random synchronized public double nextGaussian() { // See Knuth, ACP, Section 3.4.1 Algorithm C. if (haveNextNextGaussian) { haveNextNextGaussian = false; return nextNextGaussian; } else { double v1, v2, s; do { v1 = 2 * nextDouble() - 1; // between -1 and 1 v2 = 2 * nextDouble() - 1; // between -1 and 1 s = v1 * v1 + v2 * v2; } while (s >= 1 || s == 0); double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s); nextNextGaussian = v2 * multiplier; haveNextNextGaussian = true; return v1 * multiplier; } } with recursive t0(v1, v2, s, num1, num2, rn) as ( select #v1:= rand() * 2 - 1, #v2:= rand() * 2 - 1, #s:= #v1*#v1 + #v2*#v2, sqrt(-2 * log(#s) / (#s)) * #v1, sqrt(-2 * log(#s) / (#s)) * #v2, #rn:=case when #s < 1 and #s > 0 then 1 else 0 end union all select #v1:= rand() * 2 - 1, #v2:= rand() * 2 - 1, #s:= #v1*#v1 + #v2*#v2, sqrt(-2 * log(#s) / (#s)) * #v1, sqrt(-2 * log(#s) / (#s)) * #v2, #rn:=case when #s < 1 and #s > 0 then 1 else 0 end + #rn from t0 where #rn < 100 ) select 175 + t1.num1 * 10, 175 + t1.num2 * 10, 25 + t1.num1 * 8, 25 + t1.num2 * 8 from t0 t1 where t1.num1 is not null order by t1.num1 ;
Is it possible to use GROUP BY with GROUP_CONCAT on same column with limit condition
SELECT id,businessName,GROUP_CONCAT(id) FROM tbl_business LIMIT 0,1 Above query is giving me below results 1 Camp San Fransisco 1,4 Now if i apply GROUP BY and limit on same query, GROUP_CONCAT column is not giving me same results as before. SELECT id,businessName,GROUP_CONCAT(id) FROM tbl_business GROUP BY id LIMIT 0,1 Query Results 1 Camp San Fransisco 1 I'm using GROUP BY id for fetching a unique records with some where condition. Is there are any alternatives for using GROUP_BY with GROUP_CONCAT or any other methods for MySQL which can be usefull here. I want to preserve first query results with id so i just have to call second query based on first results id if it is possible. I can not remove GROUP BY id because of multiple table's LEFT JOIN and some SUB QUERY are depends on it Above queries are just for explanation purpose , original query is much longer. Actual Query : SELECT bs.id,bs.businessName,bs.businessDesc,bs.latitude,bs.longitude,bs.slug,bs.contactNo,bs.location,bs.isAddedBy,bs.createdDate,cat.categoryName as category,GROUP_CONCAT(DISTINCT(bcat.categoryName) SEPARATOR ', ') as subcategory, (SELECT COUNT(id) FROM tbl_reviews WHERE referenceId = bs.id) as totalReview, (SELECT CEIL(AVG(rating)) FROM tbl_reviews WHERE referenceId = bs.id) as avgRating, (SELECT imageName FROM tbl_business_images as bimg WHERE bimg.businessId = bs.id LIMIT 1) as bImage, ( (ACOS ( SIN(37.09024 * PI() / 180) * SIN(bs.latitude * PI() / 180) + COS(37.09024 * PI() / 180) * COS(bs.latitude * PI() / 180) * COS( (-95.712891 - bs.longitude) * PI() / 180) )* 180 / PI() ) * 60 * 1.1515 * 1.609344 ) as distance, (SELECT (DATEDIFF(bs.createdDate,NOW()) * 5) + ((SELECT COUNT(id) FROM tbl_business_images WHERE businessId = bs.id) * 2) + ((SELECT count(id) FROM tbl_business_views WHERE businessId = bs.id) * 2) + ((SELECT COUNT(id) FROM tbl_reviews WHERE referenceId = bs.id) * 10)) as totalPoint FROM tbl_business as bs LEFT JOIN tbl_category as cat ON bs.businessCat = cat.id LEFT JOIN tbl_business_subcategories as bsubs ON bs.id = bsubs.businessId LEFT JOIN tbl_category as bcat ON bsubs.subcategoryId = bcat.id WHERE bs.isActive = 'y' GROUP BY bs.slug Current Query Output : id businessName businessDesc latitude longitude slug contactNo location isAddedBy createdDate category subcategory totalReview avgRating bImage distance totalPoint 1 test test 45.14 -122.82 test 1234567890 USA c 2018-09-29 11:38:58 Category Subcategory1,subcategory2 1 5 image.png 2382.763331498852 -4 Any help is appreciated.
Print Prime Numbers with SQL query
I am new to StackOverflow and have got stuck with a query to print prime numbers from 2 to 1000. I have used the below query need input if this is the most efficient way to code it. WITH NUM AS ( SELECT LEVEL N FROM DUAL CONNECT BY LEVEL <= 1000 ) SELECT LISTAGG(B.N,'-') WITHIN GROUP(ORDER BY B.N) AS PRIMES FROM ( SELECT N, CASE WHEN EXISTS ( SELECT NULL FROM NUM N_INNER WHERE N_INNER .N > 1 AND N_INNER.N < NUM.N AND MOD(NUM.N, N_INNER.N)=0 ) THEN 'NO PRIME' ELSE 'PRIME' END IS_PRIME FROM NUM ) B WHERE B.IS_PRIME='PRIME' AND B.N!=1; I know this question has been asked multiple times and I am requesting better solution if any. More over need input on how this works with MySQL/MS SQL/PostgreSQL. Any help will make my understanding better.
In PostgreSQL probably the most fastest query that prints prime numbers up to 1000 is: SELECT regexp_split_to_table('2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997',E',')::int AS x ; It took only 16 ms on my computer. Note: a list of prime numbers was copied from https://en.wikipedia.org/wiki/Prime_number and pasted into this long string If you prefer SQL, then this works WITH x AS ( SELECT * FROM generate_series( 2, 1000 ) x ) SELECT x.x FROM x WHERE NOT EXISTS ( SELECT 1 FROM x y WHERE x.x > y.x AND x.x % y.x = 0 ) ; It's two times slower - 31 ms. Ans an equivalent version for Oracle: WITH x AS( SELECT level+1 x FROM dual CONNECT BY LEVEL <= 999 ) SELECT x.x FROM x WHERE NOT EXISTS ( SELECT 1 FROM x y WHERE x.x > y.x AND remainder( x.x, y.x) = 0 ) ;
The most obvious improvement is that instead of checking from 1 to n you can check from 1 to the square root of n. A second major optimization would be to use a temporary table to store the results and check them first. This way you can iterate incrementally from 1 to n, and only check the known primes from 1 to square root of n (recursively doing that until you have a list). If you go about things this way you would probably want to set up the prime detection in a function and then do the same with your number series generator. That second one though means extending SQL and so I don't know if that fits your requirements. For postgresql I would use generate_series go generate the list of numbers. I would then create functions which would then either store the list of primes in a temporary table or pass them back in and out in an ordered array and then couple them like that
MariaDB (with sequence plugin) Similar to kordirkos algorithm: select 2 as p union all select n.seq from seq_3_to_1000_step_2 n where not exists ( select 1 from seq_3_to_32_step_2 q where q.seq < n.seq and n.seq mod q.seq = 0 ); Using LEFT JOIN: select 2 as p union all select n.seq from seq_3_to_1000_step_2 n left join seq_3_to_32_step_2 q on q.seq < n.seq and n.seq mod q.seq = 0 where q.seq is null; MySQL There are no sequence generating helpers in MySQL. So the sequence tables have to be created first: drop temporary table if exists n; create temporary table if not exists n engine=memory select t2.c*100 + t1.c*10 + t0.c + 1 as seq from (select 0 c union all select 1 c union all select 2 c union all select 3 c union all select 4 c union all select 5 c union all select 6 c union all select 7 c union all select 8 c union all select 9 c) t0, (select 0 c union all select 1 c union all select 2 c union all select 3 c union all select 4 c union all select 5 c union all select 6 c union all select 7 c union all select 8 c union all select 9 c) t1, (select 0 c union all select 1 c union all select 2 c union all select 3 c union all select 4 c union all select 5 c union all select 6 c union all select 7 c union all select 8 c union all select 9 c) t2 having seq > 2 and seq % 2 != 0; drop temporary table if exists q; create temporary table if not exists q engine=memory select * from n where seq <= 32; alter table q add primary key seq (seq); Now similar queries can be used: select 2 as p union all select n.seq from n where not exists ( select 1 from q where q.seq < n.seq and n.seq mod q.seq = 0 ); select 2 as p union all select n.seq from n left join q on q.seq < n.seq and n.seq mod q.seq = 0 where q.seq is null; sqlfiddle
Oracle and without inner select in getting part: with tmp(id) as ( select level id from dual connect by level <= 100 ) select t1.id from tmp t1 JOIN tmp t2 on MOD(t1.id, t2.id) = 0 group by t1.ID having count(t1.id) = 2 order by t1.ID ;
/* Below is my solution */ /* Step 1: Get all the numbers till 1000 */ with tempa as ( select level as Num from dual connect by level<=1000 ), /* Step 2: Get the Numbers for finding out the factors */ tempb as ( select a.NUm,b.Num as Num_1 from tempa a , tempa b where b.Num<=a.Num ), /*Step 3:If a number has exactly 2 factors, then it is a prime number */ tempc as ( select Num, sum(case when mod(num,num_1)=0 then 1 end) as Factor_COunt from tempb group by Num ) select listagg(Num,'&') within group (order by Num) from tempc where Factor_COunt=2 ;
Tested on sqlite3 WITH nums(n) AS ( SELECT 1 UNION ALL SELECT n + 1 FROM nums WHERE n < 100 ) SELECT n FROM ( SELECT n FROM nums ) WHERE n NOT IN ( SELECT n FROM nums JOIN ( SELECT n AS n2 FROM nums ) WHERE n <> 1 AND n2 <> 1 AND n <> n2 AND n2 < n AND n % n2 = 0 ORDER BY n ) AND n <> 1 Tested on Vertica 8 WITH seq AS ( SELECT ROW_NUMBER() OVER() AS n FROM ( SELECT 1 FROM ( SELECT date(0) + INTERVAL '1 second' AS i UNION ALL SELECT date(0) + INTERVAL '100 seconds' AS i ) _ TIMESERIES tm AS '1 second' OVER(ORDER BY i) ) _ ) SELECT n FROM (SELECT n FROM seq) _ WHERE n NOT IN ( SELECT n FROM ( SELECT s1.n AS n, s2.n AS n2 FROM seq AS s1 CROSS JOIN seq AS s2 ORDER BY n, n2 ) _ WHERE n <> 1 AND n2 <> 1 AND n <> n2 AND n2 < n AND n % n2 = 0 ) AND n <> 1 ORDER BY n
This is what worked for me in the SQL server. I tried to reduce the order of my nested loops. declare #var int declare #i int declare #result varchar (max) set #var = 1 select #result = '2&3&5' --first few obvious prime numbers while #var < 1000 --the first loop begin set #i = 3; while #i <= #var/2 --the second loop which I attempted to reduce the order begin if #var%#i = 0 break; if #i=#var/2 begin set #result = #result + '&' + CAST(#var AS VARCHAR) break; end else set #i = #i + 1 end set #var = #var + 1; end print #result
SELECT LISTAGG(PRIME_NUMBER,'&') WITHIN GROUP (ORDER BY PRIME_NUMBER) FROM ( SELECT L PRIME_NUMBER FROM ( SELECT LEVEL L FROM DUAL CONNECT BY LEVEL <= 1000 ), ( SELECT LEVEL M FROM DUAL CONNECT BY LEVEL <= 1000 ) WHERE M <= L GROUP BY L HAVING COUNT(CASE WHEN L/M = TRUNC(L/M) THEN 'Y' END ) = 2 ORDER BY L );
SELECT GROUP_CONCAT(NUMB SEPARATOR '&') FROM ( SELECT #num:=#num+1 as NUMB FROM information_schema.tables t1, information_schema.tables t2, (SELECT #num:=1) tmp ) tempNum WHERE NUMB<=1000 AND NOT EXISTS( SELECT * FROM ( SELECT #nu:=#nu+1 as NUMA FROM information_schema.tables t1, information_schema.tables t2, (SELECT #nu:=1) tmp1 LIMIT 1000 ) tatata WHERE FLOOR(NUMB/NUMA)=(NUMB/NUMA) AND NUMA<NUMB AND NUMA>1 )
MySQL Code : DECLARE #i INT, #a INT, #count INT, #p nvarchar(max) SET #i = 1 WHILE (#i <= 1000) BEGIN SET #count = 0 SET #a = 1 WHILE (#a <= #i) BEGIN IF (#i % #a = 0) SET #count = #count + 1 SET #a = #a + 1 END IF (#count = 2) SET #P = CONCAT(#P,CONCAT(#i,'&')) SET #i = #i + 1 END PRINT LEFT(#P, LEN(#P) - 1)
The below code works to find prime numbers in SQL Tested on SampleDB of local server CREATE procedure sp_PrimeNumber(#number int) as begin declare #i int declare #j int declare #isPrime int set #isPrime=1 set #i=2 set #j=2 while(#i<=#number) begin while(#j<=#number) begin if((#i<>#j) and (#i%#j=0)) begin set #isPrime=0 break end else begin set #j=#j+1 end end if(#isPrime=1) begin SELECT #i end set #isPrime=1 set #i=#i+1 set #j=2 end end I have created the stored procedure which has a parameter #number to find the prime numbers up to that given number In order to get the prime numbers we can execute the below stored procedure EXECUTE sp_PrimeNumber 100 -- gives prime numbers up to 100 If you are new to stored procedures and want to find the prime numbers in SQL we can use the below code Tested on master DB declare #i int declare #j int declare #isPrime int set #isPrime=1 set #i=2 set #j=2 while(#i<=100) begin while(#j<=100) begin if((#i<>#j) and (#i%#j=0)) begin set #isPrime=0 break end else begin set #j=#j+1 end end if(#isPrime=1) begin SELECT #i end set #isPrime=1 set #i=#i+1 set #j=2 end This code can give the prime numbers between 1 to 100. If we want to find more prime numbers edit the #i and #j arguments in the while loop and execute
Simple query in PostgreSQL: SELECT serA.el AS prime FROM generate_series(2, 100) serA(el) LEFT JOIN generate_series(2, 100) serB(el) ON serA.el >= POWER(serB.el, 2) AND serA.el % serB.el = 0 WHERE serB.el IS NULL Enjoy! :)
For SQL Server We can use below CTE SET NOCOUNT ON ;WITH Prim AS ( SELECT 2 AS Value UNION ALL SELECT t.Value+1 AS VAlue FROM Prim t WHERE t.Value < 1000 )SELECT * FROM Prim t WHERE NOT EXISTS( SELECT 1 FROM prim t2 WHERE t.Value % t2.Value = 0 AND t.Value != t2. Value) OPTION (MAXRECURSION 0)
One simple one can be like this select level id1 from dual connect by level < 2001 minus select distinct id1 from (select level id1 from dual connect by level < 46) t1 inner join (select level id2 from dual connect by level < 11) t2 on 1=1 where t1.id1> t2.id2 and mod(id1,id2)=0 and id2<>1
Simplest method For SQL Server DECLARE #range int = 1000, #x INT = 2, #y INT = 2 While (#y <= #range) BEGIN while (#x <= #y) begin IF ((#y%#x) =0) BEGIN IF (#x = #y) PRINT #y break END IF ((#y%#x)<>0) set #x = #x+1 end set #x = 2 set #y = #y+1 end
MySQL QUERY SOLUTION I have solved this problem in mysql which is following: SET #range = 1000; SELECT GROUP_CONCAT(R2.n SEPARATOR '&') FROM ( SELECT #ctr2:=#ctr2+1 "n" FROM information_schema.tables R2IS1, information_schema.tables R2IS2, (SELECT #ctr2:=1) TI WHERE #ctr2<#range ) R2 WHERE NOT EXISTS ( SELECT R1.n FROM ( SELECT #ctr1:=#ctr1+1 "n" FROM information_schema.tables R1IS1, information_schema.tables R1IS2, (SELECT #ctr1:=1) I1 WHERE #ctr1<#range ) R1 WHERE R2.n%R1.n=0 AND R2.n>R1.n ) Note: No. of information_schema.tables should be increased for more range e.g. if range is 100000 so set the info tables by checking yourself.
--Create Table prime_number_t create table prime_number_t ( integervalue_c integer not null primary key ); --Insert Data into table prime_number_t INSERT ALL into prime_number_t(integervalue_c) values (1) into prime_number_t(integervalue_c) values (2) into prime_number_t(integervalue_c) values (3) into prime_number_t(integervalue_c) values (4) into prime_number_t(integervalue_c) values (5) into prime_number_t(integervalue_c) values (6) into prime_number_t(integervalue_c) values (7) into prime_number_t(integervalue_c) values (8) into prime_number_t(integervalue_c) values (9) into prime_number_t(integervalue_c) values (10) SELECT 1 FROM DUAL; COMMIT; --Write an SQL statement to determine which of the below numbers are prime numbers --same query works for REMAINDER function also instead of MOD function WITH cte_prime_number_t AS ( select integervalue_c from prime_number_t order by integervalue_c ), cte_maxval AS ( select max(integervalue_c) AS maxval FROM cte_prime_number_t ), cte_level AS ( select LEVEL+1 as lvl from dual, cte_maxval CONNECT BY LEVEL <= cte_maxval.maxval ) SELECT DISTINCT cpnt.integervalue_c as PrimeNumbers FROM cte_prime_number_t cpnt inner join cte_level cl on lvl <= (SELECT maxval FROM cte_maxval) WHERE NOT EXISTS ( SELECT 1 FROM cte_level cpn WHERE cpnt.integervalue_c > cpn.lvl AND mod(cpnt.integervalue_c,cpn.lvl) = 0 ) order by PrimeNumbers;
For MySQL 8 or above /* create a table with one row and that starts with 2 ends at 1000*/ SET cte_max_recursion_depth = 1001; /* works for MySQL 8.0*/ ;WITH RECURSIVE sequence AS ( SELECT 1 AS l UNION ALL SELECT l + 1 AS value FROM sequence WHERE sequence.l < 1000 ), /* create a caretesian product of a number to other numbers uptil this very number so for example if there is a value 5 in a row then it creates these rows using the table below (5,2), (5,3), (5,4), (5,5) */ J as ( SELECT (a.l) as m , (b.l) as n FROM sequence a, sequence b WHERE b.l <= a.l) , /*take a row from column 1 then divide it with other column values but group by column 1 first, note the completely divisible count*/ f as ( SELECT m , SUM(CASE WHEN mod(m,n) = 0 THEN 1 END) as fact FROM J GROUP BY m HAVING fact = 2 ORDER BY m ASC /*this view return numbers in descending order so had to use order by*/ ) /* this is for string formatting, converting a column to a string with separator &*/ SELECT group_concat(m SEPARATOR '&') FROM f;
This worked for me in MySql: select '2&3&5&7&11&13&17&19&23&29&31&37&41&43&47&53&59&61&67&71&73&79&83&89&97&101&103&107&109&113&127&131&137&139&149&151&157&163&167&173&179&181&191&193&197&199&211&223&227&229&233&239&241&251&257&263&269&271&277&281&283&293&307&311&313&317&331&337&347&349&353&359&367&373&379&383&389&397&401&409&419&421&431&433&439&443&449&457&461&463&467&479&487&491&499&503&509&521&523&541&547&557&563&569&571&577&587&593&599&601&607&613&617&619&631&641&643&647&653&659&661&673&677&683&691&701&709&719&727&733&739&743&751&757&761&769&773&787&797&809&811&821&823&827&829&839&853&857&859&863&877&881&883&887&907&911&919&929&937&941&947&953&967&971&977&983&991&997'; Well, I know the above one is just hardcoded and you will be able to run the problem but it's not what we should go for as a programmer so here is my solution for oracle: SELECT LISTAGG(L1,'&') WITHIN GROUP (ORDER BY L1) FROM (Select L1 FROM (SELECT LEVEL L1 FROM DUAL CONNECT BY LEVEL<=1000) Where L1 <> 1 MINUS select L1 from (SELECT LEVEL L1 FROM DUAL CONNECT BY LEVEL<=1000) A , (SELECT LEVEL L2 FROM DUAL CONNECT BY LEVEL<=1000) B Where L2<=L1 and MOD(L1,L2)=0 AND L1<>L2 AND L2<>1);
Worked in Oracle: SELECT LISTAGG(a,'&') WITHIN GROUP (ORDER BY a) FROM(WITH x AS( SELECT level+1 x FROM dual CONNECT BY LEVEL <= 999 ) SELECT x.x as a FROM x WHERE NOT EXISTS ( SELECT 1 FROM x y WHERE x.x > y.x AND remainder( x.x, y.x) = 0 ));
SELECT GROUP_CONCAT(distinct PRIME_NUMBER SEPARATOR '&') FROM (SELECT #prime:=#prime + 1 AS PRIME_NUMBER FROM information_schema.tables CROSS JOIN (SELECT #prime:=1) r WHERE #num <1000 ) p WHERE NOT EXISTS ( SELECT * FROM (SELECT #divisor := #divisor + 1 AS DIVISOR FROM information_schema.tables CROSS JOIN (SELECT #divisor:=1) r1 WHERE #divisor <=1000 ) d WHERE MOD(PRIME_NUMBER, DIVISOR) = 0 AND PRIME_NUMBER != DIVISOR) ; enter code here Explanation: The two inner SELECTs (SELECT #prime and SELECT #divisor) create two lists. Both of them contain numbers from 1 to 1000. The first list is the "list of potential primes" and the second is the "list of divisors" Then, we iterate over the list of the potential primes (the outer SELECT), and for each number from this list we look for divisors (SELECT * FROM clause) that can divide the number without a reminder and are not equal to the number (WHERE MOD... clause). If at least one such divisor exists, the number is not prime and is not selected (WHERE NOT EXISTS... clause).
How to use value from two different rows of a table in another table
I have a MySQL table with the following structure and data: Increments id emp_id starting_salary increment_rate increment_frequency 2 340 5000 250 1 3 340 5000 250 4 I need to have aliases, a and b which will hold some value based on the following formula: starting_salary + (increment_rate * increment_frequency) To be precise, I want a = 5250 (based on a = (5000 + (250 * 1))) and b = 6000 (based on b = (5000 + (250 * 4))) Now I have another table with the following data: PaySlips id employee_id salary_month arrear 173824 340 '2015-06-01' 2350 I want to join a and b that I got from the table Increments with table PaySlips. And I want to use a and b in the following way: ((a * 8) / 30 + (b * 22) / 30) My alias will be basic_salary. So basic_salary will hold this value from the above calculation: basic_salary = ((a * 8) / 30 + (b * 22) / 30) = ((5250 * 8) / 30 + (6000 *22) / 30) = (1400 + 4400) = 5800 I've got no idea how to do this. Can anyone please help me? All I got are the common columns in both tables - emp_id and employee_id and I can join both tables using these columns. I just can't figure out how I can store the above values and organize the calculation inside my query. Sample query: SELECT x.id, x.employee_id, (*my calculation using a and b from table Increments*) AS basic_salary, x.salary_month, x.arrear FROM PaySlips x JOIN Increments y ON x.employee_id = y.emp_id For determining a: SELECT ( starting_salary + (increment_rate * increment_frequency) ) AS a FROM Increments WHERE id = 2 And for determining b: SELECT ( starting_salary + (increment_rate * increment_frequency) ) AS b FROM Increments WHERE id = 3 MySQL version: 5.2
I'm not clear on all the details, for example what should happen if there are three rows for one employee in increments? Anyhow, here's a sketch to start with: select employee_id , ((a * 8) / 30 + (b * 22) / 30) as basic_salary from ( select x.employee_id , min(starting_salary + (increment_rate * increment_frequency)) as a , max(starting_salary + (increment_rate * increment_frequency)) as b , x.salary_month, x.arrear from payslips x join increments y on x.employee_id = y.emp_id group by x.employee_id, x.salary_month, x.arrear ) as t If id 2 and 3 are the criteria (I assumed they are examples) you can use a case statement like: select employee_id , ((a * 8) / 30 + (b * 22) / 30) as basic_salary from ( select x.employee_id , max(starting_salary + (increment_rate * case when y.id = 2 then increment_frequency end )) as a , max(starting_salary + (increment_rate * case when y.id = 3 then increment_frequency end)) as b , x.salary_month , x.arrear from payslips x join increments y on x.employee_id = y.emp_id group by x.employee_id, x.salary_month, x.arrear ) as t; In this case it does not matter what aggregate you use, it is to get rid of the row that contains null.
based on the requirements you added i think something like this will solve your problems: SELECT PS.id, PS.employee_id, ((A.value * 8) / 30 + (B.value * 22) / 30) AS basic_salary FROM PaySlips AS PS JOIN ( SELECT I.emp_id, I.starting_salary + (increment_rate * increment_frequency) AS VALUE FROM Increments AS I WHERE I.id = 2 ) AS A ON A.emp_id = PS.employee_id JOIN ( SELECT I.emp_id, I.starting_salary + (increment_rate * increment_frequency) AS value FROM Increments AS I WHERE I.id = 3 ) AS B ON B.emp_id = PS.employee_id This version might need some alteration if it's not working on your real scenario, but please feel free to tell if anything else needs amending. Hope it helps.
For determining and setting #a variable: SET #a := (SELECT ( starting_salary + (increment_rate * increment_frequency) ) AS a FROM Increments WHERE id = 2); And for determining and setting #b variable: SET #b := (SELECT ( starting_salary + (increment_rate * increment_frequency) ) AS b FROM Increments WHERE id = 3); Then you can use #a and #b in your main query; you can test simply by SELECT #a as a; SELECT #b as b;
SELECT x.id, x.employee_id, (y.a * 8) / 30 + (y.b * 22) / 30 as basic_salary, x.salary_month, x.arrear FROM PaySlips x JOIN ( select t1.emp_id, t1.a, t2.b from ( select emp_id, starting_salary + increment_rate * increment_frequency as a from Increments where id = 2 ) as t1 join ( select emp_id, starting_salary + increment_rate * increment_frequency as b from Increments where id = 3 ) as t2 on t1.emp_id = t2.emp_id ) as y ON x.employee_id = y.emp_id
Calculating an Equation from a MySql Query
How can i select as result of an equation like this ( decimalnumber_1 / (100+decimalnumber_2) * 100 ) with a mysql query decimalnumber_1 = //SELECT table_1.a_decimalnumber_1 AS decimalnumber_1 FROM table_1 WHERE table_1.another_coloumn_name = z decimalnumber_2 = //SELECT table_2.a_decimalnumber_2 AS decimalnumber_2 FROM table_2 WHERE table_2.an_another_coloumn_name = x result = //SELECT ( decimalnumber_1 / (100+decimalnumber_2) * 100 ) AS result
CREATE PROCEDURE #eqresult #result int output AS DECLARE #decNum1 int,#decNum2 int SET #decNum1=(SELECT table_1.a_decimalnumber_1 AS decimalnumber_1 FROM table_1 WHERE table_1.another_coloumn_name = z) SET #decNum1=(SELECT table_2.a_decimalnumber_2 AS decimalnumber_2 FROM table_2 WHERE table_2.another_coloumn_name = x) SET #result=( #decNum1 / (100+#decNum2) * 100 ) RETURN #result
Try SELECT ( (SELECT table_1.a_decimalnumber_1 AS decimalnumber_1 FROM table_1 WHERE table_1.another_coloumn_name = z )/ (100+(SELECT table_2.a_decimalnumber_2 AS decimalnumber_2 FROM table_2 WHERE table_2.an_another_coloumn_name = x )) * 100 ) AS result