I'm trying to get from an decimal(13.6) value to currency in EURO's
I'm getting this as result right now:
╔══════════════╦═════════╗
║ total ║ Date ║
╠══════════════╬═════════╣
║8887616.500000║ 2017 ║
╚══════════════╩═════════╝
What I want is something like this one:
╔══════════════╦═════════╗
║ total ║ Date ║
╠══════════════╬═════════╣
║€8,887.616.50 ║ 2017 ║
╚══════════════╩═════════╝
Or this one:
╔══════════════╦═════════╗
║ total ║ Date ║
╠══════════════╬═════════╣
║ €M8,9 ║ 2017 ║
╚══════════════╩═════════╝
I did try to convert from decimal but had no luck with that
SELECT SUM(totalExcl) AS total, DATE_FORMAT(date_add, '%Y') AS 'Date'
FROM ex.ps_oxo_quotation
WHERE saleType IN ('IEW' , 'As', 'Pr')
AND date_add >= '2017-01-01 00:00:00'
GROUP BY 'Date'
ORDER BY 'Date' DESC
This will give you a sum formatted in Euro:
SELECT CONCAT('€', FORMAT(SUM(totalExcl), 2, 'de_DE')) AS total
Will show: €8.890.905,86
The other requested alternative:
SELECT CONCAT('€M', FORMAT((SUM(totalExcl)/1000000), 1, 'de_DE')) AS total
Will show: €M8,9
Note that this example will show the sum according to standards (LOCALE de_DE), and not with the exact format you have requested, that have mixed dots "." and commas "," in a non standard way. This could easily be fixed with some string manipulation if you really must format the sum that way.
Related
I have column which has values like this
"BEAAL - Aalter - Belgium - EMEA"
I want to create a table where I want to split it in to multiple columns
Location = BEAAL - Aalter
Country = Belgium
Region = EMEA
So my table should look like this
'ID' 'Text' 'Location' 'Country' 'Region'
'1 ' 'BEAAL - Aalter' 'BEAAL - Aalter' 'Belgium' 'EMEA'
How can this be achieved in SQL Server 2008? I have around 1000 entries in table to split this way.
This script produces what you want, using a slightly modified version of the SplitStrings function you can find in this answer. All credit to Aaron Bertrand for that function.
Modified SplitStrings function:
CREATE FUNCTION [dbo].[SplitStrings](#List NVARCHAR(MAX))
RETURNS TABLE
AS
RETURN ( SELECT Item=LTRIM(RTRIM(Item)),Id FROM
( SELECT Item = x.i.value('(./text())[1]', 'nvarchar(max)'),Id=x.i.value('for $i in . return count(../*[.<<$i])+1','INT')
FROM ( SELECT [XML] = CONVERT(XML, '<i>'
+ REPLACE(#List, '-', '</i><i>') + '</i>').query('.')
) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
WHERE Item IS NOT NULL
);
The script:
DECLARE #t TABLE(id int identity(1,1), blabla VARCHAR(512));
INSERT INTO #t(blabla)VALUES('BEAAL - Aalter - Belgium - EMEA');
INSERT INTO #t(blabla)VALUES('YYYY - Gent - Belgium - XXXX');
INSERT INTO #t(blabla)VALUES('ZZZZZ - Brussel - Belgium - WWWWW');
SELECT
t.id,
Location=MAX(CASE WHEN split.Id=1 THEN split.Item END)+' - '+MAX(CASE WHEN split.Id=2 THEN split.Item END),
Country=MAX(CASE WHEN split.Id=3 THEN split.Item END),
Region=MAX(CASE WHEN split.Id=4 THEN split.Item END)
FROM
#t AS t
CROSS APPLY dbo.SplitStrings(blabla) AS split
GROUP BY
t.Id;
The result:
╔════╦═════════════════╦═════════╦════════╗
║ id ║ Location ║ Country ║ Region ║
╠════╬═════════════════╬═════════╬════════╣
║ 1 ║ BEAAL - Aalter ║ Belgium ║ EMEA ║
║ 2 ║ YYYY - Gent ║ Belgium ║ XXXX ║
║ 3 ║ ZZZZZ - Brussel ║ Belgium ║ WWWWW ║
╚════╩═════════════════╩═════════╩════════╝
Here is my table
Type Amount Year Month
P 10 2016 1
P 15 2016 2
T 5 2016 1
T 20 2016 3
There will only be one month-year combination for P and T. In other words, there cannot be two rows with P having the same Year and Month combination.
Here's what I'd like to do
Get the difference in amount (amount in P row minus amount in T row) where month and year are the same. If there is no corresponding P or T row, then assume amount is 0. So the output would be
Amount Year Month
5 2016 1
15 2016 2
-20 2016 3
What is the simplest way of doing this (by simple, I mean least amount of code repetition). One way I can think of is to first get the P and T rows into two separate derived tables (using select statements), then do a left join union with a right join, but this involves a lot of code repetition.
You could use conditional aggregation:
SELECT `Year`, `Month`,
SUM(CASE WHEN `Type` = 'P' THEN `Amount` ELSE -`Amount` END) AS Amount
FROM tab
GROUP BY `Year`, `Month`;
Output:
╔══════╦═══════╦════════╗
║ Year ║ Month ║ Amount ║
╠══════╬═══════╬════════╣
║ 2016 ║ 1 ║ 5 ║
║ 2016 ║ 2 ║ 15 ║
║ 2016 ║ 3 ║ -20 ║
╚══════╩═══════╩════════╝
LiveDemo
Using IF function:
SELECT `Year`, `Month`,
SUM(IF(`Type` = 'P', `Amount`, -`Amount`)) AS Amount
FROM tab
GROUP BY `Year`, `Month`;
Another way is to use UNION ALL:
SELECT `Year`, `Month`, SUM(`Amount`) AS Amount
FROM (SELECT `Year`, `Month`, `Amount`
FROM tab
WHERE `Type` = 'P'
UNION ALL
SELECT `Year`, `Month`, -`Amount`
FROM tab
WHERE `Type` = 'T') AS sub
GROUP BY `Year`, `Month`;
LiveDemo2
I have a table whose structure is as follows
╔════════╦══════════╦════════════╗
║ app_id ║ app_name ║ categoryId ║
╠════════╬══════════╬════════════╣
║ 1200 ║ A ║ B ║
║ 1200 ║ A ║ C ║
║ 1200 ║ A ║ D ║
║ 1201 ║ E ║ F ║
║ 1201 ║ E ║ G ║
╚════════╩══════════╩════════════╝
Now I have 1600 such data. What I am trying to get is, a query to fetch data till the number of distinct appids reaches 200. After 200 is reached it should no longer fetch the rest of the data. I tried count(distinct(app_id)) but that doesn't seem to work the way I think. I am really struck here and it is a major performance issue. Any help is much appreciated. Thanks in advance.
You can try like this:
SELECT app_id
FROM myTable
GROUP BY app_id
HAVING COUNT(distinct app_id) < 200;
If what you want is
a query to fetch data till the number of distinct appids reaches 200
then you can use variables to implement this:
SELECT app_id, app_name, categoryId
FROM (
SELECT app_id, app_name, categoryId,
#appIDcnt := IF (#appID = app_id,
IF(#appID := app_id, #appIDcnt, #appIDcnt),
IF(#appID := app_id, #appIDcnt+1, #appIDcnt+1)) AS cnt
FROM mytable
CROSS JOIN (SELECT #appID := 0, #appIDcnt := 0) AS vars
ORDER BY app_id ) AS t
WHERE t.cnt <= 200
In the above query #appIDcnt variable is used to count distinct app_id values. The query fetches table data until #appIDcnt value reaches 200.
Demo here
use limit it will return the first 200 results only.
SELECT DISTINCT ap_id FROM appTable LIMIT 200
and then if you need to get the next 200 then use offset 200 which will start with row 201
SELECT DISTINCT ap_id FROM ap_Table LIMIT 200 OFFSET 200
i have two tables for example:
BALANCE VS
╔══════╦══════╗ ╔══════╦═══════╗
║ V_ID ║ BAL ║ ║ V_ID ║ NAME ║
╠══════╬══════╣ ╠══════╬═══════╣
║ 1 ║ 1000 ║ ║ 1 ║ Carl ║
║ 1 ║ 500 ║ ║ 2 ║ Peter ║
║ 1 ║ -200 ║ ╚══════╩═══════╝
║ 2 ║ 350 ║
║ 2 ║ 1000 ║
╚══════╩══════╝
Now i've done a query like:
select
NAME,sum(BAL)
from VS,BALANCE
where VS.V_ID = BALANCE.V_ID
group by NAME
And the result is:
╔═══════╦══════╗
║ NAME ║ BAL ║
╠═══════╬══════╣
║ Carl ║ 1300 ║
║ Peter ║ 1350 ║
╚═══════╩══════╝
But i'd like to know how its done without the ´group by´ clause. Something like a subquery.
I tried different things but i cant figure out how it would work. I always end with results like all the values summed up into one row or results like the above one but without grouping.
may be anyone could help me
greetings
edit:forgot sum()
To get your current SQL to work using GROUP BY you would need the following (ie the SUM aggregate function):-
select NAME, SUM(BAL)
from VS, BALANCE
WHERE VS.V_ID = BALANCE.V_ID
group by NAME
Note that this is just your original SQL minimally modified to work and it still uses the implicit join you coded. Implicit joins should generally be avoided and better to use explicit INNER JOIN....ON syntax:-
select NAME, SUM(BAL)
from VS
INNER JOIN BALANCE
ON VS.V_ID = BALANCE.V_ID
group by NAME
If you really want to avoid the GROUP BY then it is possible using a sub query, but is likely to be slower (as it effectively has to perform an extra query for every row tha main query returns):-
select NAME, (SELECT SUM(BAL) FROM BALANCE WHERE BALANCE.V_ID = VS.V_ID)
from VS
EDIT, in response to your comment on sub queries.
Correlated sub queries effectively force MySQL to get a result set, and then for each row on the result set to perform another query. Most of the time they are used to get an aggregate value (such as the max value of a field related to a row on the returned row, but where GROUP BY on the main query would not be viable).
For example if you had a list of comments for a user, but on each row you wanted to know the date of the latest comment from that user you might do the following:-
SELECT users.user_name, comments.comment_date, (SELECT MAX(comment_date) FROM comments WHERE comments.user_id = users.id) AS latest_comment_date
FROM users
INNER JOIN comments
ON users.id = comments.user_id
This could be written to do a non correlated sub query using GROUP BY which is then joined:-
SELECT users.user_name, comments.comment_date, latest_comment_date
FROM users
INNER JOIN comments
ON users.id = comments.user_id
INNER JOIN
(
SELECT user_id, MAX(comment_date) AS latest_comment_date
FROM comments
GROUP BY user_id
) sub1
ON users.id = sub1.user_id
If you are dealing with a large number of records on users this would likely be faster.
However if you were only dealing with a tiny number of records on users (and determining that number was quite complex), getting ALL the max comment dates would be an unnecessary overhead, and it forces a join against a sub query which isn't likely to use indexes.
Try joining tables:
select NAME,BAL from VS JOIN BALANCE ON VS.V_ID = BALANCE.V_ID
Will return
NAME | BAL
-------------
Carl | 1000
Carl | 500
Carl | -200
Peter| 350
Peter| 1000
To get sum of BAL, you have to use GROUP BY, otherwise you will get SUM of all rows
I am using MySQL, I have 50 records in employee table. I want to find the person with the 22nd highest salary.
Use LIMIT, specifying both an offset and a row count.
To get the 22nd ranked person in order of highest salary, do:
SELECT person
FROM employee
ORDER BY salary DESC
LIMIT 21, 1
Notice the use of 21 here. This is because the offset of the initial row (1st highest salary) is actually 0. Therefore the 22nd highest salary will actually be an offset of 21 (the 21st row in 0-based counting, or "skip 21 rows").
To get the person(s) with the 22nd highest salary, you will need one more level of indirection. Try:
SELECT person
FROM employee
WHERE salary = (
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 21, 1
)
here's another one, considering you have duplicate salary number. I guess limit won't correct solve your case if you have some duplicates. Try something like this,
SELECT aa.*
FROM table1 aa
INNER JOIN
(
SELECT #row:=#row+1 rankNo,
a.Salary
FROM (SELECT DISTINCT Salary FROM table1) a,
(SELECT #row:=0) s
ORDER BY Salary DESC
) bb ON aa.Salary = bb.Salary AND
bb.rankNo = 2
SQLFiddle Demo
consider you have records like this,
CREATE TABLE Table1
(`EmpID` int, `Salary` int);
INSERT INTO Table1
(`EmpID`, `Salary`)
VALUES
(1, 10),
(2, 12), -- duplicate
(3, 11),
(4, 12), -- duplicate
(5, 14),
(6, 12); -- duplicate
╔═══════╦════════╗
║ EMPID ║ SALARY ║
╠═══════╬════════╣
║ 1 ║ 10 ║
║ 2 ║ 12 ║
║ 3 ║ 11 ║ -- you want to get this value (*2nd from the last value*)
║ 4 ║ 12 ║
║ 5 ║ 14 ║
║ 6 ║ 12 ║
╚═══════╩════════╝
SELECT MIN(salary) FROM (
SELECT DISTINCT salary FROM employee ORDER BY salary DESC LIMIT 22
) limited_salary
Just answered a similar question here: select all rows except the four most recent
In your case, you'll want to LIMIT to 1, and OFFSET to the 22 position.
LIMIT 21,1
How to find n'th highest value of a column?
Query to find nth max value of a column