How to define Query within LIKE statement - mysql

I use this query to match data from two tables but it returns
Error Code: 1242
Subquery returns more than 1 row
my example tables and query are below.
SELECT
ACCOUNT_CODE,
DR_AMOUNT,
CR_AMOUNT
FROM
`tblinvoices`
WHERE ACCOUNT_CODE LIKE
CONCAT((
SELECT
LEFT(SUB_GROUP, 4)
FROM
`tblcharts`
WHERE ACC_TYPE = 'G'), '%') ;
Temp Table.
SUB_GROUP
------------------
1-01
2-01
3-01
4-01
6-01
6-02
6-03
7-01
7-02
8-01
9-01
DATA TABLE TBLINVOICES
ACCOUNT_CODE DR_AMOUNT CR_AMOUNT
------------ --------- -----------
6-03-0001 27500 0
6-02-0001 0 27500
6-03-0001 1700 0
6-02-0001 0 1700
3-01-0005 15000 0
6-03-0001 0 15000
6-03-0001 315432 0
6-02-0002 0 315432
I want to get all debit and credit amounts where match first 4 character of group code with invoice account code. Please anyone help in this regards.

I think you want an aggregation query. It would look something like this:
SELECT LEFT(i.ACCOUNT_CODE, 4) as sub_group, SUM(i.DR_AMOUNT) as DR_AMOUNT,
SUM(i.CR_AMOUNT) as CR_AMOUNT
FROM tblinvoices i
GROUP BY LEFT(i.ACCOUNT_CODE, 4);

I believe you can do what you want, using a subquery in the like clause BUT you must be sure that the subquery returns only one result: does not make sense to database to compare a single line of tblinvoices to a lot of lines.
You can achieve what you want narrowing the results in subquery's where clause. Also, as long as you comparing just a fraction of the whole field, I believe you should concat '%' characters at the end of the result of the subquery,or it will never match!
Put the data/format of tblcharts so I can help in a more detailed way.

Related

How to use CASE to select MAX(date) WHEN active=1? (without subquery)

I'm trying to optimize some code, if this is possible it's not only more elegant but it would save me running several other queries to get the same data and speed up my while loop considerably.
How would I CASE select the MAX (date) where it is also 1 from a dataset like this?
0 2020-06-30
0 2020-06-26
1 2020-06-25 <---- I want this guy
0 2020-06-24
0 2020-06-24
0 2020-06-23
0 2020-06-22
0 2020-06-22
0 2020-06-16
0 2020-06-16
0 2020-06-12
1 2020-06-12
0 2020-06-11
0 2020-06-01
0 2020-06-01
I tried something like this but obviously this doens't work.
CASE
WHEN aty.type_count = '1' AND ac.activity_date = MAX(ac.activity_date)
THEN ac.activity_date
ELSE 0
END
AS max_date_active
I can't just sort by both columns as sometimes there are no 1 results. I guess I could make the result set a query, but I am running other SUM(CASE())'s on the same data set, so I'm trying to make it all work together as a single, elegant query.
Any ideas?
EDIT: I updated the name to "without subquery" as once I'm using a subquery I might as well just create a separate query to get the results. I'm curently thinking I just get the entire data set back, and figure out what I want using a PHP loop. Not as elegant but at least it saves several complex joined queries.
A LIMIT query might be the easiest option here:
SELECT *
FROM yourTable
WHERE type_count = '1'
ORDER BY activity_date DESC
LIMIT 1;
If there might be more than one record with a type count of 1, tied for the latest date, then we can use a subquery:
SELECT *
FROM yourTable t1
WHERE
type_count = '1' AND
activity_date = (SELECT MAX(activity_date) FROM yourTable WHERE type_count = '1');
As far as I can tell it's not possible to do exactly what I wanted. Subqueries are possible but if I'm processing the query twice inside itself I'd rather handle them separately.
In the end I just kept the result set shown in my question, and then did a basic loop in PHP to extract the info I wanted.

I need to create a query with a dynamic range of value in mysql

I have a table with a column called "Points", the value of this column have a min value of 0, and a max value of 100.000. I have to do an analysis per range of this column, so I wrote a query like this:
select case when Points between 0 and 5000 then '0 - 5000'
when Points between 5001 and 20000 then '50001 - 20000'
when Points > 20000 then '> 20000'
else 0 end RangeP
from Sales
The problem is that the customer wants to see for each 2.000 points from 0 to 100.000
If I wrote the query using the case, the query will get really big, so I'd like one way to get dynamically this range.
It is possible? Thank you very much
You may create a table which contains the ranges, and their text labels, and then join to it, e.g.
SELECT
s.Points,
COALESCE(r.label, 'range not found') AS range
FROM Sales s
LEFT JOIN
(
SELECT 0 AS start, 2000 AS end, '0 - 2000' AS label UNION ALL
SELECT 2001, 4000, '2001 - 4000' UNION ALL
...
SELECT 98000, 100000, '98000 - 100000'
) r
ON s.Points BETWEEN r.start AND r.end;
I have inlined the table of ranges, but you may create a formal table (or maybe a temp table) instead, and then replace the above subquery with just a reference to that table.

Need help returning duplicates from a join onto a single line with a sum function included

I have two tables t1 and t2. t1 contains some message data i have set up to be searched against t2 which contains a list of keywords all with their own individual score. Now I have been moderately successful with this and have managed to return all rows in t1 that contain any keyword within t2 with this query
SELECT DISTINCT t1.RowID, t1.ChatNo, t1.UserNo,
t1.Chat, t2.Keywords, SUM(t2.KeywordScore) AS Score
FROM t1
LEFT JOIN t2 ON t1.Chat LIKE CONCAT('%', + t2.Keywords , + '%')
WHERE t2.Keywords IS NOT NULL OR t1.ChatNo > 0 AND t1.UserNo > 0
GROUP BY t1.RowID, t2.Keywords
Now my issue is, it returns duplicate results if a chat message has multiple keywords and on each duplicate row it will have picked up a different keyword and that keywords score. Now because of this I believe my query is attempting to sum the rows individually so cannot total them up (correct me if i am wrong).
for example:
RowID ChatNo UserNO Chat Keywords Score
1 1 1 "...ex1 ex2 ex3" ex1 2
1 1 1 "...ex1 ex2 ex3" ex2 4
1 1 1 "...ex1 ex2 ex3" ex3 1
Now what I would like it to do is to return all the keywords found in a message on a single line (or list) and still be able to SUM up the values of the keywords found within the message and display the total, like so:
RowID ChatNo UserNO Chat Keywords Score
1 1 1 "...ex1 ex2 ex3" ex1, ex2, ex3 7
I have done some searching and testing haven't really come across a solution that has worked for me. So if anyone can give me some assistance on how I might proceed and get the query to output the results on a single line with a the score summed up it would be greatly appreciated.
You need to use GROUP_CONCAT()
Also distinct doesn't seem necessary so I deleted it.
Try this:
SELECT t1.RowID, t1.ChatNo, t1.UserNo,
t1.Chat, group_concat(t2.Keywords, ', '), SUM(t2.KeywordScore) AS Score
FROM t1
LEFT JOIN t2 ON t1.Chat LIKE CONCAT('%', + t2.Keywords , + '%')
WHERE t2.Keywords IS NOT NULL OR t1.ChatNo > 0 AND t1.UserNo > 0
GROUP BY t1.RowID, t1.ChatNo, t1.UserNo, t1.Chat

return row even if all no value found in table mysql

I Have a select where I am trying to return a row even if there is nothing to be found from the select.
Here is the select
select
1 as risk_management,
0 as Borrow,
0 as Interest,
IFNULL(d.symbol,'E') as symbol,
IFNULL(d.Abbreviation,'EUR') as Abbreviation,
IFNULL(sum(round((a.amount_financed - a.amount_invested - a.amount_withdrawn) * i.average_rate / j.average_rate, 2)),0) as LendingOffers,
IFNULL( min(a.Interest),0) as InterestLend,
0 as VolumePerDay,
0 as LatestId,
0 as InterestLatestRealized,
0 as InterestBorrowLow,
IFNULL(max(a.Interest),0) as InterestLendHigh
from market_cap a
where ........more statements here...
But when I run this select I still get nothing returned.
I would like mysql to generate a row that has 0 for numbers and 'E' and 'EUR' if the value is missing, I thought IFNULL works for that after searching other stackoverflow but its not working in my case.
Since I don't have your data I cannot test the query for you, but I can demonstrate you the basic idea.
You need to create a buffer table with your default data as the main subselect of your query. In my example, it is called "dv" as in "default values".
The query which fetches the real values is also a subquery in the from clause. In my example, it is called "rv" as in "real values".
I use a left (outer) join on to join both select statements with a condition which is always true (on 1 = 1).
Therefore, when the query which fetches the real values cannot find any results, we can still use the values in the default table.
select
IFNULL(rv.risk_management, dv.risk_management) as risk_management,
IFNULL(rv.Borrow, dv.Borrow) as Borrow,
IFNULL(rv.Interest, dv.Interest) as Interest,
IFNULL(rv.symbol, dv.symbol) as symbol,
IFNULL(rv.Abbreviation, dv.Abbreviation) as Abbreviation,
IFNULL(rv.LendingOffers, dv.LendingOffers) as LendingOffers,
IFNULL(rv.InterestLend, dv.InterestLend) as InterestLend,
IFNULL(rv.VolumePerDay, dv.VolumePerDay) as VolumePerDay,
IFNULL(rv.LatestId, dv.LatestId) as LatestId,
IFNULL(rv.InterestLatestRealized, dv.InterestLatestRealized) as InterestLatestRealized,
IFNULL(rv.InterestBorrowLow, dv.InterestBorrowLow) as InterestBorrowLow,
IFNULL(rv.InterestLendHigh, dv.InterestLendHigh) as InterestLendHigh
from (
1 as risk_management,
0 as Borrow,
0 as Interest,
'E' as symbol,
'EUR' as Abbreviation
0 as LendingOffers,
0 as InterestLend,
0 as VolumePerDay,
0 as LatestId,
0 as InterestLatestRealized,
0 as InterestBorrowLow,
0 as InterestLendHigh
) as dv
LEFT JOIN (
select
risk_management,
Borrow,
Interest,
d.symbol,
d.Abbreviation,
sum(round((a.amount_financed - a.amount_invested - a.amount_withdrawn) * i.average_rate / j.average_rate, 2)) as LendingOffers,
min(a.Interest) as InterestLend,
VolumePerDay,
LatestId,
InterestLatestRealized,
InterestBorrowLow,
max(a.Interest) as InterestLendHigh
from market_cap a
where ........more statements here...
) AS rv
ON 1 = 1
Good succes and have a nice day Masnad Nihit

Ignore columns in MySQL query result with null values

I have a MySql table as,
Name Month Salary
=======================================
A Salary_Month_Sept 15000
A Salary_Month_Oct 0
B Salary_Month_Sept 12000
B Salary_Month_Oct 0
C Salary_Month_Sept 13000
C Salary_Month_Oct 0
and I am querying that table as
select Name,
max(IF(Month = 'Salary_Month_Sept', Salary, 0)) AS 'Salary_Month_Sept',
max(IF(Month = 'Salary_Month_Oct', Salary, 0)) AS 'Salary_Month_Oct'
from myTable
Which returns the query result as
Name Salary_Month_Sept Salary_Month_Oct
=============================================
A 15000 0
B 12000 0
C 17000 0
How can i ignore the column containing only zero or null values from the above query result.
Don't use *. Name columns you want to have. The query is not a crystal ball. It doesn't know in front if there will be data for the column. To do something like that you need 2 queries, assuming the salaries are only positive:
Select sum(salary_sept), sum(salary_oct), ... for the condition you need.
Create second select only for columns returning sum bigger than zero.
The SQL has no time machine, sorry. You have to do your work yourself.