简体   繁体   中英

Select by length of characters

I have to select the longest phrase that has points>0 but being contained in a phrase which has points=0 , if you look at the demo than the rows in output would be number 3 and 6:

http://sqlfiddle.com/#!18/e954f/1/0

many thanks in advance.

You can use an inner join comparing the phrases with a LIKE to get only the ones contained in another phrase. Filter for the point in a WHERE clause. Then get the rank() partitioned by the phrase from the joined instance and ordered by the length descending. In an outer SELECT only get the ones with a rank of one.

SELECT x.id,
       x.phrase,
       x.points
       FROM (SELECT w1.id,
                    w1.phrase,
                    w1.points,
                    rank() OVER (PARTITION BY w2.phrase
                                 ORDER BY len(w1.phrase) DESC) r
                    FROM words w1
                         INNER JOIN words w2
                                    ON w2.phrase LIKE concat(w1.phrase, '%')
                    WHERE w2.points = 0
                          AND w1.points > 0) x
       WHERE x.r = 1;

SQL Fiddle


Edit:

To include the other phrase:

SELECT x.id,
       x.phrase,
       x.other_phrase,
       x.points
       FROM (SELECT w1.id,
                    w1.phrase,
                    w2.phrase other_phrase,
                    w1.points,
                    rank() OVER (PARTITION BY w2.phrase
                                 ORDER BY len(w1.phrase) DESC) r
                    FROM words w1
                         INNER JOIN words w2
                                    ON w2.phrase LIKE concat(w1.phrase, '%')
                    WHERE w2.points = 0
                          AND w1.points > 0) x
       WHERE x.r = 1;

You can use a CTE to find all phrases with positive points which are a substring of a phrase with 0 points. Then you can find the maximum length of the substrings associated with each 0 point phrase, and JOIN that back to the CTE to get the phrase that matches that condition:

WITH cte AS (
SELECT w1.*, w2.id AS w2_id
FROM words w1
JOIN (SELECT * 
      FROM words
      WHERE points = 0) w2 ON w1.phrase = LEFT(w2.phrase, LEN(w1.phrase))
WHERE w1.points > 0
)
SELECT cte.id, cte.phrase, points
FROM cte
JOIN (SELECT w2_id, MAX(LEN(phrase)) AS max_len
      FROM cte
      GROUP BY w2_id) cte_max ON cte_max.w2_id = cte.w2_id AND cte_max.max_len = LEN(cte.phrase)

Output:

id  phrase              points
3   tool box online     1
6   stone road          1

Updated SQLFiddle

You will get from max to min length of phrase where points>0

SELECT *, LEN(phrase) AS Lenght FROM words where points>0 ORDER BY LEN(phrase) DESC

And if you want the longest phrase

 SELECT TOP 1 *, LEN(phrase) AS Lenght FROM words where points>0 ORDER BY LEN(phrase) DESC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM