I have a table as below
------------------------------------
| Date | Price |
------------------------------------
| 09-13-2017 | $15.00 |
| 09-13-2017 | $6.00 |
| 09-15-2017 | $8.00 |
| 09-15-2017 | $14.50 |
|__________________________________|
I want to sum the total values of each Date so the output would be
Total value for 09-13-2017 is $21.00
Total value for 09-15-2017 is $22.50
How do i do this in JavaScript. Kindly guide.
var dat = jQuery("#date").map(function()
{
totpri = 0;
var pri = jQuery("#price").map(function()
{
var totpri = document.getElementByID("price").value();
totpri += totpri;
}
alert('The Total is: ' totpri)
}).get();
I can give you a technique you can use but not the code ( since I don't see your effort )
Step 1: create an empty associative array (say arrDates)
Step 2: Iterate through each row and check if the array contains a key with the keyname as 1st column(date)
If NOT => create a new entry in the format: {'date' => amount}
If YES => get the old amount for that date, and add the current amount to it, update the amount in the array
That's it
Now you can iterate this array and display the dates and amount sum in whatever format you want
Related
I have a table with DBName, SCName, Number. I wrote a procedure that inserts the DBName, SCName into the table and deletes a row when a Number is 0. I used merge to avoid duplicates and insert based on the condition but I don't understand how to delete a row when a Number=0.
------------------------
|DBName| SCName| Number|
| DB1 | SC1 | 1 |
| DB2 | SC2 | 0 | <-- Need to delete row
| DB2 | SC3 | 2 |
| DB2 | SC1 | 4 |
| DB3 | SC4 | 0 | <-- Need to delete row
------------------------
Here is my Procedure:
CREATE TABLE TABL(DBName VARCHAR, SCName VARCHAR); // creating table
CREATE OR REPLACE PROCEDURE repo(DB VARCHAR,SC VARCHAR)
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
//inserting values into table using merge
//if values are already present and Number = 0 then I need to delete row
var sql_command = `merge into TABL as t
using (SELECT :1 as database,:2 as schema) as s
on t.DBName = s.database
and t.SCName = s.schema
when matched then update
set t.DBName = t.DBName
when not matched then insert
(DBName, SCName) VALUES (:1,:2)`;
snowflake.execute({sqlText: sql_command, binds: [DB, SC]});
return 'success';
$$;
I didn't understand in which case (MATCHED / NOT MATCHED) the rows with '0' should be deleted from the target table.
But in general you have only can use DELETE in the MATCH-case:
when matched and number=0 then delete
It is important to avoid a nondeterministic result for the merge (see link below under "Duplicate Join Behavior"). Solution therefor is to also add "and number!=0" to your "when matched then update"-clause.
More infos: https://docs.snowflake.com/en/sql-reference/sql/merge.html
EDIT: I posted wrong information. For MATCH you can Delete and Update, for NOT MATCH you can INSERT.
I have two sheets with a dozen of columns and thousands of rows. Each sheet has a column A that contains a unique ID. I want to compare two sheets using only the column A as a point of comparison and generate a third sheet that contains entire rows with the unique ID that is in Sheet 1 but not in Sheet 2.
Here is a visualisation:
Sheet 1
+---+--------+-----+-----+
| | A | B | C |
+---+--------+-----+-----+
| 1 | 1111 | xxx | zzz |
| 2 | 2222 | yyy | zzz |
| 3 | 2222-1 | zzz | xxx |
| 4 | 3333 | xxx | yyy |
+---+--------+-----+-----+
Sheet 2
+---+------+-----+-----+
| | A | B | C |
+---+------+-----+-----+
| 1 | 1111 | xxx | zzz |
| 2 | 2222 | yyy | zzz |
| 3 | 3333 | xxx | yyy |
+---+------+-----+-----+
The desired function would compare Sheet 1 and Sheet 2 using A as the basis and the function would point out that the cell sheet1[A2] is unique, it would copy the entire 2:2 row, and then it would paste it into a newly generated sheet. The content of B and C is irrelevant in comparison.
I wanted to create a loop that would go and compare each cell in column A for both sheets and if sheet1.A[n] != sheet2.A[n], but it would work only if both sheets had the same lengths.
In the case I've specified above, the loop I've created with the help of the user Cooper finds that row 3 is unique and after that everything will be unique because of a misalignment.
The sheets will always be of different lengths and the uniques may appear at different spots (i.e. 2222-1 may end up the next time I'm making a comparison at row 5).
function compareSheetDrop(input) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//establish first sheet and get its data range
var dropSheet = ss.getSheetByName("Drop (2)");
var dropRange = dropSheet.getRange(2, 1, dropSheet.getLastRow() - 1, dropSheet.getLastColumn());
var vA1 = dropRange.getValues();
//establish the sheet with new data and get its data range
var compareSheet = ss.getSheets()[4];
var compareRange = compareSheet.getRange(2, 1, compareSheet.getLastRow() - 1, compareSheet.getLastColumn());
var vA2 = compareRange.getValues();
//establish the sheet with results
var resultSheet = ss.getSheetByName("ADQA");
for (var i = 0; i < vA1.length; i++) {
//i've tried to make the loop stop once it encounters a blank cell to avoid a type error, but doesn't work
if (vA2[i][0] === '' || vA1[i][0] === '') {
break;
}
else if (vA1[i][0] != vA2[i][0]) {
Logger.log(vA1[i][0] + " & " + vA2[i][0]);
resultSheet.appendRow(vA2[i]);
}
}
}
Even if my code doesn't provide results I want, there are also two problems with it:
It loops until there's a TypeError: Cannot read property "0" from undefined. that I've tried to combat but to no avail.
Moreover, the appendRow method doesn't write data in already existing cells but inserts the row before the already existing ones - after running my test script 3 times the results sheet had thousands of columns and was barely operable.
Any ideas how I could modify my existing code to get what I want while avoiding the aforementioned issues? Or does it require a completely new approach? Any suggestions?
Flow:
Use Array#map to get all of sheet1 col A in a array(say a).
Use Array#filter to filter sheet2 by the array above.
Use the filtered array directly in setValues()
Snippet:
var a1 = [[1,'x','z'],[2,'y','z'],[3,'m','z'],['2-1','x','z']];//sheet1ValuesArr
var a2 = [[1,'x','z'],[2,'y','z'],[3,'m','z']];//Sheet2ValuesArr
var a = a2.map(function(e){ return e[0]}); //Sheet2Col A : [1,2,3]
var filteredArr = a1.filter(function(e){return !~a.indexOf(e[0])});
console.log(filteredArr); //to use in setValues
resultSheet.getRange(1, 1, filteredArr.length, filteredArr[0].length).setValues(filteredArr)
References:
Array#Filter
Range#setValues(array)
I am trying to create the following query with subqueries using Knex:
SELECT
t.*,
(SELECT COUNT(*) FROM team_users tu WHERE TeamID = t.ID) AS UserCount,
(SELECT COUNT(*) FROM team_access ta WHERE TeamID = t.ID) AS AppCount
FROM teams t WHERE OwnerUserID = _UserID;
The result should be the teams table with a count aggregation of UserCount and AppCount from different tables (team_users, team_access)
id | Name | OwnerUserID | UserCount | AppCount
-----------------------------------------------------
134| Team A | 1538 | 7 | 6
135| Team B | 1538 | 4 | 2
136| Team C | 1538 | 12 | 1
What I figured to be an equivalent knex implementation was:
var subquery1 = Knex.knex('team_users').count('*').where('TeamID', 'teams.ID').as('UserCount');
var subquery2 = Knex.knex('team_access').count('*').where('TeamID', 'teams.ID').as('AppCount');
Knex.knex.select('*', subquery1, subquery2).from('teams').where("OwnerUserID", ownerId).asCallback(dataSetCallback);
Running that, I do get the "UserCount" and "AppCount" columns in the returned object but always as zero, probably because it doesn't identify the 'teams.ID' in the subquery.
I managed to solve it using the Knex.raw function:
Knex.knex('teams')
.select('*', Knex.knex.raw('(SELECT COUNT(*) FROM team_users WHERE TeamID = teams.ID) AS UserCount'), Knex.knex.raw('(SELECT COUNT(*) FROM team_access WHERE TeamID = teams.ID) AS AppCount'))
.where("OwnerUserID", ownerId)
.asCallback(dataSetCallback);
but I am curious to know how to achieve this with the subqueries objects.
You are trying to pass teams.ID string as a value. To be able to do .where('columnName', 'otherColumnName') one has to use knex.ref to pass otherColumnName as an identifier.
var teamsIdColumnIdentifier = knex.ref('teams.ID'); // <-- [1]
var subquery1 = Knex.knex('team_users').count('*')
.where('TeamID', teamsIdColumnIdentifier).as('UserCount');
var subquery2 = Knex.knex('team_access').count('*')
.where('TeamID', teamsIdColumnIdentifier).as('AppCount');
Knex.knex.select('*', subquery1, subquery2).from('teams')
.where("OwnerUserID", ownerId).asCallback(dataSetCallback);
[1] Before knex.ref was added to Knex in May 2018, you had to use knex.raw, like this;
var teamsIdColumnIdentifier = knex.raw('??', ['teams.ID']);
I want to select data from a table, get the result in JavaScript and print it in a graph (x = date, y = numbers)
I have the following DATA table (note: I tried to put it in markdown so it appears as an HTML table, but it doesn't seems to work):
| date | number |
|---------|--------|
| 2015-01 | 12 |
| 2015-02 | 7 |
| 2015-04 | 4 |
and the following SQL select:
SELECT date_format(date, '%Y-%m') AS date, number
FROM DATA
WHERE date >= '2015-01' AND date <= '2015-05'
GROUP BY date
ORDER BY date;
which gives me exactly the same table as output. However, what I'd want is a row per each months with 0 if the month is not recorded. For instance, March is not recorded in the database, so the result that I want:
| date | number |
|---------|--------|
| 2015-01 | 12 |
| 2015-02 | 7 |
| 2015-03 | 0 |
| 2015-04 | 4 |
| 2015-05 | 0 |
the table goes to May, because in the SELECT I want every months between January and May.
The question is: is there a way to do it in SQL, or do I have to post-process the results in JavaScript to add the empty months in my final table?
thanks for your help
edit: the begin and end dates are variable and can cover several years. So, I guess it is possible to do something with a special table containing the months but I have no idea how...
If the answer is to post-process, it's OK (disappointing but OK ^^)
edit2: the problem is "gap filling" as stated #mauro. It looks quite complex in MySQL, so I'm going to post-process my request.
see How to fill date gaps in MySQL?
I would create a second table DATA2 with one row per month and number=zero. Then, instead of selecting:
FROM DATA
I would select from:
FROM ( SELECT * FROM DATA UNION ALL SELECT * FROM DATA2 ) D
This way... if DATA contains values for a given month, you will get totals from DATA, if not... you will get zero from DATA2
Here is a sample with no temp table. it use the sequence ENGINE. The only difference is you must fill the start date an the count of month (seq_0_to_4).
SELECT `DATE`, SUM(number) as number
FROM (
SELECT
date_format( IF(d.`DATE` IS NULL, init.`DATE`, d.`DATE`) ,'%Y-%m') AS `DATE`
, IF(d.number IS NULL,0,d.number) as number
FROM (
SELECT '2015-01-01' + INTERVAL seq MONTH AS `DATE`, 0 AS number
FROM seq_0_to_4
) AS INIT
LEFT JOIN DATA d ON date_format(d.`DATE`,'%Y-%m') = date_format( init.`DATE` ,'%Y-%m')
) AS result
GROUP BY `DATE`
ORDER BY `DATE`;
Result
+---------+--------+
| DATE | number |
+---------+--------+
| 2015-01 | 7 |
| 2015-02 | 0 |
| 2015-03 | 7 |
| 2015-04 | 0 |
| 2015-05 | 0 |
+---------+--------+
5 rows in set (0.00 sec)
Table
MariaDB > select * from data;
+------------+--------+
| date | number |
+------------+--------+
| 2015-01-01 | 4 |
| 2015-01-02 | 3 |
| 2015-03-05 | 7 |
+------------+--------+
3 rows in set (0.00 sec)
MariaDB >
So I am trying something out in Google Spreadsheet with GAS,
Let's say I have a bunch of values in the the 1st row like so:
| A | B | C | D | E | F |
1 | Apple | Orange | Banana | Pear | Lime | Melon |
What I would like then, is to have a function where you input a string like "Orange", and it would check which column "Orange" is in, and then output that column index. So with "Orange" it would return "B" as it is in column "B"/ Or just the index numeric "index".
Any suggestions?
or is more explanation needed?
I'm new to programming - so there are probably better, more elegant and more efficient ways to do it, but this seems to work (thanks to WhiteHat for the hints)
function isInColumn(searchString) {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("DATA"); //insert your sheetname
var columns = "ABCDEFGHIJKLMNOPYRSTUVWXYZ"; // make a kind of index
var range = sheet.getRange("A1:G"); // range is first row from A to G
var values = range.getValues();
var array = [];
for (i in values[0])
{
array.push(values[0][i]) // values is a 2D array
}
var indexNumber = array.indexOf(searchString); // get the position
var column = columns.charAt(indexNumber); // match this position to 'kind of index'
return column;
}
Search for "Orange" will return "B". Maybe you can go from here.