MYSQL Ordering Substring Count - php

i want to order my query by counts of the substring.
Table :
id shop_update
1 a,b,c
2 a,b
3 c
4 a,'',c
I just to order this by count
id shop_update count
1 a,b,c 3
2 a,b 2
3 c 1
4 a,'',c 2
My query is
$this->db->select("*,LENGTH(shop_update) - LENGTH(REPLACE(shop_update,',','')) AS counts");
$this->db->order_by("counts","DESC");
$this->db->from('at_shop');
but it returns 0 only in the count
id shop_update count
1 a,b,c 0
2 a,b 0
3 c 0
4 a,'',c 0
my issue is LENGTH(REPLACE(REPLACE(shop_update,',',''),'''','')) it was running with space like LENGTH(REPLACE(REPLACE(shop_update,', ',''),'''',''))
(spaces are added between (', ')in the query but actual code the spaces are not there)
Please see the difference
Any help?

Just by using this function in the query will give you the correct count:
LENGTH(REPLACE(REPLACE(shop_update,',',''),"' '",''))
See a working example of the same here: http://www.sqlfiddle.com/#!2/fa7a5/7

SELECT *
FROM tablename
ORDER BY LENGTH( REPLACE( shop_update, ',', '' ) ) DESC

You may use this command
SELECT id,shop_update,LENGTH(replace(shop_update,"''","")) as count FROM table_name ORDER BY count desc

Related

I want to sort my CatId in this order 1 2 3 4 1 2 3 4 but there is a catch that it first check allocationId last 14 digits if catid is same

My query is this:-
SELECT m.allocationID,mt.CatId,mt.CatSName
FROM msttransaction m,msttemp mt WHERE m.isPending='Y'
AND m.allocationID IN (
SELECT mt.AllocationId FROM msttemp WHERE mt.quarterId='010100001'
) ORDER BY SUBSTRING(m.AllocationId, -14)
output:-
12980013120170919125006 1 A
12980013320170919125404 3 C
12980013420170919125603 4 D
12980013820170919130113 2 B
12980013920170919130315 3 C
12980014020170919130519 4 D
12980013220170919130613 2 B
12980013720170919130722 1 A
In 129800 series last 14 digits is date and time. First I have to sort my output according to 1 2 3 4 1 2 3 4 but first it check last 14 digits of 129800 of same catId that comes first which comes first.
Expected output
12980013120170919125006 1 A
12980013820170919130113 2 B
12980013320170919125404 3 C
12980013420170919125603 4 D
12980013720170919130722 1 A
12980013220170919130613 2 B
12980013920170919130315 3 C
12980014020170919130519 4 D
Does this do it?
ORDER BY m.CatId, SUBSTRING(m.AllocationId, -14)
The point is to order first by that CatId, then order by the embedded datastamp in the AllocationId.
If it were me I'd be more formal about the datestamp ordering, by formally extracting it from your strings using STR_TO_DATE() like this. This isn't strictly necessary, but good practice anyhow.
ORDER BY m.CatId, STR_TO_DATE(SUBSTRING(m.AllocationId, -14), '%Y%m%d%H%i%s'))
Plus, then you could use date manipulation like
ORDER BY m.CatId, LAST_DAY(STR_TO_DATE(SUBSTRING(m.AllocationId, -14), '%Y%m%d%H%i%s')))
to gather all the datestamps in a month together for ordering, or some such thing.
Here's an example: http://sqlfiddle.com/#!9/1c87ee/6/0
You can introduce a variable that will give you the order of the CatId when the result set would have been ordered by CatId and then the 14 last digits of the AllocationId. So in your example this variable would be either 1 or 2.
Once you have that variable value for each record, you can sort by that value first, and then by CatId:
select t.allocationId, CatId
from (
select t.*,
#rn := if(#CatId = CatId, #rn+1, if(#CatId := CatId, 1, 1)) rn
from (
SELECT m.allocationID, mt.CatId,mt.CatSName
FROM msttransaction m,
INNER JOIN msttemp mt
ON m.allocationID = mt.AllocationId
WHERE m.isPending='Y'
AND mt.quarterId='010100001'
ORDER BY CatId, SUBSTRING(m.AllocationId, -14)
) t,
(select #CatId := -1, #rn := -1) init
) t
order by rn, CatId;

Filtering SQL Results with Tags in a Junction Table [duplicate]

Lets consider the following table-
ID Score
1 95
2 100
3 88
4 100
5 73
I am a total SQL noob but how do I return the Scores featuring both IDs 2 and 4?
So it should return 100 since its featured in both ID 2 and 4
This is an example of a "sets-within-sets" query. I recommend aggregation with the having clause, because it is the most flexible approach.
select score
from t
group by score
having sum(id = 2) > 0 and -- has id = 2
sum(id = 4) > 0 -- has id = 4
What this is doing is aggregating by score. Then the first part of the having clause (sum(id = 2)) is counting up how many "2"s there are per score. The second is counting up how many "4"s. Only scores that have at a "2" and "4" are returned.
SELECT score
FROM t
WHERE id in (2, 4)
HAVING COUNT(*) = 2 /* replace this with the number of IDs */
This selects the rows with ID 2 and 4. The HAVING clause then ensures that we found both rows; if either is missing, the count will be less than 2.
This assumes that id is a unique column.
select Score
from tbl a
where a.ID = 2 -- based off Score with ID = 2
--include Score only if it exists with ID 6 also
and exists (
select 1
from tbl b
where b.Score = a.Score and b.ID = 6
)
-- optional? ignore Score that exists with other ids as well
and not exists (
select 1
from tbl c
where c.Score = a.Score and c.ID not in (2, 6)
)

Getting next results

I have a table that is something like the one below.
id | episode_number
1 55
2 56
3 57-58
4 59
5 60
6 61-62
7 63
8 64
9 65-66
10 67-68
How would I get the next 5 episodes after 57-58 without specificity the id, just the episode_number such as episode_number > 57-58 LIMIT 5.
But obviously episode_number > 57-58 would not work since it contains string in it. The database will just consider it as 5 and return the next 5 results after the episode_number 5.
Use CAST function to convert string to number, then your query:
SELECT episode_number
FROM table_name
WHERE CAST(episode_number AS UNSIGNED) > CAST('57-58' AS UNSIGNED)
ORDER BY CAST(episode_number AS UNSIGNED)
LIMIT 5
If there are two numbers, for example: '57-58', then CAST('57-58' AS UNSIGNED) converts and returns first one: 57
Try
SELECT TOP 5 * FROM tablename WHERE id >= (SELECT id FROM tablename WHERE episode_number = "57-58")
or if it's MySQL
SELECT * FROM tablename WHERE id >= (SELECT id FROM tablename WHERE episode_number = "57-58") LIMIT 5
You can select like this:
select id , case when LOCATE('-' , episode_number) = 0 then episode_number
else LEFT(episode_number , LOCATE('-' , episode_number)) end
as start_episode ,
case when LOCATE('-' , episode_number) = 0 then episode_number
else RIGHT(episode_number , LEN(episode_number) -LOCATE('-' , episode_number)) end
as end_episode
this should give you the base structure for such queries, you should consider converting the values into numbers to be able to easily compare them.
If possible restructure the table to something that has the start episode and end episode in separated fields

get SUM of another row of GROUP BY'd rows

I have this table:
This selection is is duplicated many times for different var_lines (which pretty much work as one row of data, or respondent for a survey) and set_codes (different survey codes).
With this query:
SELECT
*, COUNT(*) AS total
FROM
`data`
WHERE
`var_name` = 'GND.NEWS.INT'
AND(
`set_code` = 'BAN11A-GND'
OR `set_code` = 'BAN09A-GND'
OR `set_code` = 'ALG11A-GND'
)
AND `country_id` = '5'
GROUP BY
`data_content`,
`set_code`
ORDER BY
`set_code`,
`data_content`
The query basically counts the number of answers for a specific question. Then groups them survey (set_code).
What I need is for each of the grouped data_content answers for GND.NEWS.INT to also show the SUM of all the corresponding GND_WT with the same var_line.
For example if I had this:
data_id data_content var_name var_line
1 2 GND.NEW.INT 1
2 1.4 GND_WT 1
3 2 GND.NEW.INT 2
4 1.6 GND_WT 2
5 3 GND.NEW.INT 3
6 0.6 GND_WT 3
I would get something like this:
data_id data_content var_name var_line total weight
1 2 GND.NEW.INT 1 2 3
5 3 GND.NEW.INT 3 1 0.6
Thanks for any help.
Your requirements are not exactly clear, but I think the following gives you what you want:
select d1.data_id,
d1.data_content,
d1.var_name,
d1.var_line,
t.total,
w.weight
from data d1
inner join
(
select data_content,
count(data_content) Total
from data
group by data_content
) t
on d1.data_content = t.data_content
inner join
(
select var_line,
sum(case when var_name = 'GND_WT' then data_content end) weight
from data
group by var_line
) w
on d1.var_line = w.var_line
where d1.var_name = 'GND.NEW.INT'
See SQL Fiddle with Demo
This Query can be suitable for your specific example:
select st.data_id,
st.data_content,
st.var_name,
st.var_line,
count(st.data_id) as total,
sum(st1.data_content) as weight
from data st
left join data st1 on st1.var_name = 'GND_WT' AND st1.var_line=st.var_line
where st.var_name='GND.NEW.INT'
group by st.data_content
Regards,
Luis.

MySQL count and total

I have a table with a number of votes recorded in it, each vote goes against a post. What I want to be able to do is count the total occurances of each vote.
Table looks like this:
vote
-----
1
2
3
1
2
3
4
5
2
2
2
2
...and so on...
How can I count the records, e.g. In that list 1x2, 2x6, 3x2, 4x1 and 5x1 times.
select vote, count(votes) as vt
from t_your_table
group by vote
To get what you want you can use GROUP BY and COUNT:
SELECT vote, COUNT(*) AS cnt
FROM votes
GROUP BY vote
Result:
vote cnt
1 2
2 6
3 2
4 1
5 1
Votes that have zero count will not be represented in this result set. If you want to have these included with a count of zero then you will need to use an OUTER JOIN with a table listing all the possible votes.
SELECT
possible_votes.vote,
COUNT(votes.vote) AS cnt
FROM possible_votes
LEFT JOIN votes ON possible_votes.vote = votes.vote
GROUP BY possible_votes.vote
Result:
vote cnt
1 2
2 6
3 2
4 1
5 1
6 0
Check MySQL manual for GROUP BY combined with COUNT.
SELECT vote, COUNT(*) as total
FROM votes
GROUP BY vote

Categories