FoxPro Conditional Sum Statement - sql

I am trying to perform a conditional sum on a column of data in a FoxPro program. I think it should be able to be done in one line or so. So far I have something that looks like:
public sumvar
sumvar = SUM(TABLE2.val WHERE table2.id = table1.id)
This is being done inside a loop, so for this instance, table1.id might equal 4, and there are say 3 rows in table2 which have table2.id = 4. So I want to sum the table2.val value for just these 3 rows together. Any help much appreciated!

I'd recommend the SQL way rather than the xBase Sum command
CLEAR
CREATE CURSOR test (id Int, amount N(15,2))
INSERT INTO test VALUES (1, 15.45)
INSERT INTO test VALUES (1, 8)
INSERT INTO test VALUES (2, 9)
GO TOP IN test
* SQL
LOCAL ARRAY laSum[1]
SELECT SUM(amount) FROM test WHERE id = 1 INTO ARRAY laSum
? laSum[1]
* xBase
SUM amount FOR id = 1 TO result
? m.result
* F1 Help says: "Totals all or specified numeric fields in the **currently selected table**"
Another disadvantage of the xBase command would be moving record pointers.

Related

Insert records into a table based on value of a record in another table

I am trying to create a quotation system using Microsoft Access 2013.
Currently, my main issue to trying to write a query that selects all records from a table (itemquote) that have a certain quoteID matching the quoteID coming from another table (currentquote), and then inserts the results into a new table (quoteditems).
Here is a basic example of the tables:
ItemQuote
UniqueID ItemID QuoteID BuyPrice SellPrice
1 1 1 10.00 11.00
2 8 2 07.00 14.00
3 4 5 01.12 03.00
CurrentQuote
CurrentQuoteID
1
My current attempt at writing the query looks like this:
INSERT INTO tblQuotedItems
SELECT *
FROM tblQuoteAsBuiltAndLabelling
INNER JOIN tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;
The resulting error message is "The INSERT INTO statement contains the following unknown field name: 'CurrentQuoteID'. Make sure you have typed the name correctly, and try the operation again." (Error 3127)
What should I do to my query to make it achieve the desired result? Thanks in advance.
The problem may be because your tblQuotedItems does not have the same number of column what your Select Query Returns.
So to resolve this, You can specified individual columns in INSERT Statement, and that will solve your problem.
You can not specify column names in the insert if the columns in the select are in the same order as in the table definition. Possibly, the columns in the current quote might be the same. If so, this might work:
INSERT INTO tblQuotedItems
SELECT tblCurrentQuote.*
FROM tblQuoteAsBuiltAndLabelling INNER JOIN
tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;
However, I strongly recommend that you include column names explicitly when you do inserts:
INSERT INTO tblQuotedItems(col1, col2, . . .)
SELECT col1, col2, . . .
FROM tblQuoteAsBuiltAndLabelling INNER JOIN
tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;

SQL. When I trying to do something like "INSERT INTO Table VALUES(x1,x2,x3) - can the x1 x2 x3 be sql queries, like SELECT <...>

I want to do something like this:
QSqlQuery q;
q.prepare("insert into Norm values(select from Disc id_disc WHERE name_disc=?, select from Spec code_spec WHERE name_spec=?,?");
q.addBindValue(MainModel->data(MainModel->index(MainModel->rowCount()-1, 1)).toString());
q.addBindValue(ui->comboBox->currentText());
q.addBindValue(MainModel->data(MainModel->index(MainModel->rowCount()-1, 2)).toString());
q.exec();
But it's not working. Surely for someone obviously where is the error and maybe he tells me how to do it right.
First of all your you have done spelling mistake. Its "INSERT" not "INCERT"
And yes we can insert SELECT query inside INSERT query.
eg:
INSERT INTO table2
(column_name(s))
SELECT column_name(s)
FROM table1;
INSERT ... SELECT ... is used when you want to insert multiple records, or when most values to be inserted come from the same record.
If you want to insert one record with values coming from several tables, you can use subqueries like you tried to do, but you have to use the correct syntax:
scalar subqueries must be written inside parentheses, and you must write the SELECT correctly as SELECT value FROM table:
INSERT INTO Norm
VALUES ((SELECT id_disc FROM Disc WHERE name_disc = ?),
(SELECT code_spec FROM Spec WHERE name_spec = ?),
?)
If you want data from two tables, you must first write a query which return pretended data - using JOIN, UNION, subqueries, ...
Then, just do
INSERT INTO target_table SELECT ...

Parse values from one column into multiple columns in another table

Microsoft SQL Server 2008
I have two tables. One has a column in it with data that is _ delimited
example:
Y_21_CA
<BR>
such that:
Yes/No_Age_State
I need to parse the data in this column out and insert it into another table that has individual columns for each value. Let's say Table A contains one column like the example above but Table B contains three columns, YesOrNo, Age, usState.
What's the easiest way to do this? I've tried doing something like:
UPDATE TableA
SET YesOrNo = SUBSTRING (TableB.Column1, 1, 1)
but SUBSTRING only takes an expression. I really just need some guidance here, I've been banging my head against the wall trying to figure this out since I'm not much of a SQL guru. I can figure out the syntax no problem but maybe I'm not aware of some methods that exist. Thanks
A generic solution, using Charindex of '_' without hardcoding it
declare #s varchar(10) = 'Y_21_CA'
SELECT LEFT(#s, CHARINDEX('_',#s,1)-1) YN,
SUBSTRING(#s, CHARINDEX('_',#s,1)+1,
CHARINDEX('_',#s,CHARINDEX('_',#s,1)) ) Age,
RIGHT(#s, CHARINDEX('_',reverse(#s),1)-1) State
--Results
Y 21 CA
In case you expect to use this logic often in other queries, you could make the SELECT statement an inline TVF. Then you would be able to use it with your update like this:
UPDATE b
SET YesOrNo = x.YN,
Age = x.Age,
State = x.State
FROM TableB b
INNER JOIN TableA a ON b.ID = a.ID
CROSS APPLY ThreeColumnSplit(a.S) x;
Here's a "live" demo at SQL Fiddle. (Please never mind its using the SQL Server 2012 engine. That's only because the Fiddle's 2008 instance appears to be down at the moment and can't be used. There's nothing SQL Server 2012-specific in the script.)
You should be able to use the following, I think you want an INSERT instead of UPDATE.
The SELECT statement to get the data is:
select substring(yourCol, 1, 1) YesOrNo,
substring(yourcol, 3, len(yourcol)-5) Age,
right(yourCol, 2) usState
from tableA;
See SQL Fiddle with Demo
Then the INSERT statement is:
insert into tableB (YesOrNo, Age, usState)
select substring(yourCol, 1, 1) YesOrNo,
substring(yourcol, 3, len(yourcol)-5) Age,
right(yourCol, 2) usState
from tableA;
See SQL Fiddle with Demo
Note: This assumes that the YesOrNo column will always only have one character and that the usState will always have 2 characters.

Short but though SQL Query (T-SQL,SQL Server)

Suppose I have 2 tables, each tables has N columns. There are NO duplicate rows in table1
And now we want to know what datasets in table2 (including duplicates) are also contained in table1.
I tried
select * from table1
intersect
select * from table2
But this only gives me unique rows that are in both tables. But I don't want unique rows, are want to see all rows in table2 that are in table1...
Keep in mind!! I cannot do
select *
from table1 a, table b
where a.table1col = b.table2col
...because I don't know the number of columns of the tables at runtime.
Sure I could do something with dynamic SQL and iterate over the column numbers but I'm asking this precisely because it seems too simple a query for that kind of stuff..
Example:
create table table1 (table1col int)
create table table2 (table2col int)
insert into table1 values (8)
insert into table1 values (7)
insert into table2 values (1)
insert into table2 values (8)
insert into table2 values (7)
insert into table2 values (7)
insert into table2 values (2)
insert into table2 values (9)
I want my query then to return:
8
7
7
If the amount of columns is not know, you will have to resort to a value computed over a row to make a match.
One such function is CHECKSUM.
Returns the checksum value computed over a row of a table, or over a
list of expressions. CHECKSUM is intended for use in building hash
indices.
SQL Statement
SELECT tm.*
FROM (
SELECT CS = CHECKSUM(*)
FROM Table2
) tm
INNER JOIN (
SELECT CS = CHECKSUM(*)
FROM Table2
INTERSECT
SELECT CHECKSUM(*)
FROM Table1
) ti ON ti.CS = tm.CS
Note that CHECKSUM might introduce collisions. You will have to test for that before doing any operation on your data.
Edit
In case you are using SQL Server 2005, you might make this a bit more robust by throwing in HASH_BYTES.
The downside of HASH_BYTESis that you need to specify the columns on which you want to operate but for all the columns you do known up-front, you could use this to prevent collisions.
EXCEPT vs INTERSECT - link
EXCEPT returns any distinct values from the left query that are not also found on the right query.
INTERSECT returns any distinct values that are returned by both the query on the left and right sides of the INTERSECT operand.
Maybe EXCEPT can solve your problem

Why does the sql select statement fail?

In the scenario below, the final select from the Combine view fails, any ideas why?
The Subset table does not have a row that corresponds to the one in MasterCodes that wouldn't cast to an integer value.
CREATE TABLE MasterCodes (
ID INT
, Code VARCHAR(10) )
GO
CREATE TABLE Subset (
ID INT )
GO
CREATE VIEW Combine AS
SELECT S.ID
, M.Code
, CAST(M.Code AS INT) IntCode
FROM Subset S
INNER JOIN MasterCodes M ON M.ID = S.ID
GO
INSERT MasterCodes (ID, Code) VALUES (1, '1')
INSERT MasterCodes (ID, Code) VALUES (2, '2')
INSERT MasterCodes (ID, Code) VALUES (3, 'three')
INSERT MasterCodes (ID, Code) VALUES (4, '4')
INSERT Subset (ID) VALUES (1)
INSERT Subset (ID) VALUES (2)
INSERT Subset (ID) VALUES (4)
SELECT * FROM Combine -- 3 rows returned
SELECT * FROM Combine WHERE Code = '2' -- 1 row returned
SELECT * FROM Combine WHERE Code = '3' -- 0 rows returned
SELECT * FROM Combine WHERE IntCode = 2 -- fails, error msg is
Msg 245, Level 16, State 1, Line 15
Conversion failed when converting the varchar value 'three' to data type int.
Environment is Sql2k5 Standard (64-bit) ON Win2k3 Server R2
Probably because in some row, M.Code contains the literal word "three", and the view is trying to cast a non-numeric looking word into an int (you can probably cast "3" into an int, but not "puppy" or "three", etc.).
Edit: Added a comment, but worthwhile to add it here. SQL Server is going to try and execute and join the as efficiently as possible, and it's going try and apply the where clause apparently even before joining.
This makes sense if you consider that VIEWs nowadays work almost fully like a real table. It has to do something SIMILAR to this; otherwise, it will join everything and return all values BEFORE being filtered out.
Hideously expensive.
What I'm not sure about is if the execution plan will show this level of detail.
You're inserting the string "three" into MasterCodes.Code, and your view is attempting to cast this value to an integer. This SQL should give the same error:
select cast("three" as int)
Solution? Replace "three" with "3" in your insert statement.
Because when you try to use IntCode in your condition logic the view try's to cast "three" as an int.
Use isnumeric() with a case statement to create the view
case when isnumeric(field) then
cast(field as int)
else
null
end AS IntCode
If your result set is accurate:
"SELECT * FROM Combine WHERE Code = '2' -- 1 row returned
SELECT * FROM Combine WHERE Code = '3' -- 0 rows returned
SELECT * FROM Combine WHERE IntCode = 2 -- fails, error msg isMsg 245, Level 16, State 1, Line 15Conversion failed when converting the varchar value 'three' to data type int."
then the only time it fails is when you try to compare against IntCode field, it almost seems like it is failing when it tries to put the non-numeric value on the left side of the "IntCode = 2" comparison, because this is the only time it will need to pick up every single value in the code field.
Hope that helps!