PHP Wizards

From: Peter (BOUGHTONP)20 Apr 2011 18:38
To: Ken (SHIELDSIT) 69 of 101
Is it giving an error or just producing the wrong result?
From: Ken (SHIELDSIT)20 Apr 2011 18:43
To: Peter (BOUGHTONP) 70 of 101

error. but I'm stuck on trying to figure out how to approach this.

 

I have the needed info in the database. So I just need to compare or count and that's where I'm stuck atm.

From: Ken (SHIELDSIT)20 Apr 2011 18:55
To: Peter (BOUGHTONP) 71 of 101
OK Pete help me!

I have this:
code:
<CFQUERY NAME="count" DATASOURCE="isiswood">
	SELECT COUNT(*) AS WoodType 
	FROM ProductionDetail WHERE rudID='041811BD' AND rudCategory='Produced' AND rudProductID LIKE '%RO%';
</cfquery>


And it's working, but how can I automate this so I don't have to put every time of shit we have. It's already in the database.
From: af (CAER)20 Apr 2011 19:02
To: Peter (BOUGHTONP) 72 of 101
Max line length matters when I have 4 columns of code visible at once. Besides, I didn't make the rule.

You make a compelling argument in favour of tabs for indenting, though.
EDITED: 20 Apr 2011 19:03 by CAER
From: Peter (BOUGHTONP)20 Apr 2011 19:26
To: Ken (SHIELDSIT) 73 of 101
Which one is the actual wood type, the rudId ?

Try something along the lines of this:

code:
<CFQUERY NAME="count" DATASOURCE="isiswood">
	SELECT rudID AS WoodType, COUNT(*) AS WoodCount
	FROM ProductionDetail WHERE rudCategory='Produced' AND rudProductID LIKE '%RO%'
	GROUP BY rudID
</cfquery>
From: Ken (SHIELDSIT)20 Apr 2011 19:31
To: Peter (BOUGHTONP) 74 of 101
Well here's the thing. The %RO% could be about 20 different things. Should I just create a table to hold what they could be and use it to loop through?
From: Peter (BOUGHTONP)20 Apr 2011 19:44
To: Ken (SHIELDSIT) 75 of 101
Oh, so "RO" is one type of wood, but the ProductID contains other stuff in addition to that?

Is it always two characters at the same location?

If so, you can use mid or substring or whatever function MSSQL uses to do this... looks like it is SUBSTRING, so...

code:
SELECT SUBSTRING(rudProductID,6,2) AS WoodType, COUNT(*) AS WoodCount
FROM ProductionDetail WHERE rudCategory='Produced'
GROUP BY SUBSTRING(rudProductID,6,2)


If the RO (and similar values) changes position in the code then you can't do that, but probably they're in the same place?
EDITED: 20 Apr 2011 19:44 by BOUGHTONP
From: Ken (SHIELDSIT)20 Apr 2011 19:45
To: Peter (BOUGHTONP) 76 of 101
Nice! Yes always in the same spot. That should be saweet!
From: Ken (SHIELDSIT)20 Apr 2011 19:53
To: Peter (BOUGHTONP) 77 of 101
That worked like a charm! Thanks!
From: Ken (SHIELDSIT)20 Apr 2011 20:40
To: Peter (BOUGHTONP) 78 of 101

OK Peter I'm stuck again.

 

I can get it to output the types and count for a query, but how can I tell it the one with the biggest number is the one I want to use?

From: Ken (SHIELDSIT)20 Apr 2011 20:52
To: Peter (BOUGHTONP) 79 of 101
Nevermind I got it. Probably not the prettiest but it's working :)
From: Peter (BOUGHTONP)20 Apr 2011 22:37
To: Ken (SHIELDSIT) 80 of 101
Did you ORDER BY counted_column DESC or something more complicated?
From: Ken (SHIELDSIT)20 Apr 2011 22:48
To: Peter (BOUGHTONP) 81 of 101

I'll show you after I eat supper. I can't remember really.

 

But I rebuilt the whole code and cleaned it all up. It required much less math and variables. So I thank you for that! Plus I formatted it as you suggested and that helps a lot.

From: Ken (SHIELDSIT)20 Apr 2011 23:26
To: Peter (BOUGHTONP) 82 of 101
This is what I did. It let me eliminate a bunch of if's and other math.
code:
<CFQUERY NAME="sluth" DATASOURCE="isiswood">
	SELECT ID=rudID, Category=rudCategory, Seq=rudSeq, Type=rudType, Product_ID=rudProductID, Description=rudDescrip, 
	PcsPerPkg=rudPcsPerPkg, Tally=rudTally, UOM=rudBaseUnitID, Pieces=rudPieces, Volume=rudVolume, NetVolume=rudNetVolume, Cost=rudCost, AddedCost= rudAddedCost, MktValue=rudMarketValue, Total=rudTotal, NetThick=rudNetThick, 
	NetWidth=rudNetWidth, NetLength=rudNetLength, NetType=rudVolType, LocationID=rudLocationID,rudFIFOVolume,rudForceCost,rudBoomID,prdLengthID=(SELECT prdLengthID 
	FROM ProductMaster WHERE prdID=rudProductID) FROM ProductionDetail WHERE rudID='#form.batch#' AND rudCategory='Produced' AND rudProductID LIKE '%#WoodType#%' AND rudDescrip NOT LIKE '%boards%' AND rudDescrip NOT LIKE '%blocking%'
	ORDER BY Seq;
</cfquery>
From: Ken (SHIELDSIT)20 Apr 2011 23:39
To: Peter (BOUGHTONP) 83 of 101
Here is my code after your help.
Attachments:
From: Peter (BOUGHTONP)21 Apr 2011 00:23
To: Ken (SHIELDSIT) 84 of 101
Much better... though still a whole bunch of stuff I want to change there. :$

But anyway, yeah, if you make it to "ORDER BY WoodCount DESC" in your count query, then all you need is <cfset WoodType = Count.WoodType[1] /> instead of that cfoutput loop.

(Or, you can skip that entirely, and later on just use #Count.WoodType[1]# directly.)

You can probably save a small bit of memory by putting a "TOP 1" after the SELECT too, since by then you'll only care about the first row, but it'll still work without that, just not as efficiently.


All this is just an internal tool, yes - not something that will be publicly available?

In general, you should never directly do #form.whatever# or #url.whatever# or #cookie.whatever# inside a cfquery, because it potentially allows people to inject SQL, which is bad.

Solution is to use query parameters, like this:
code:
AND rudID = <cfqueryparam value="#form.batch#" />


Which prevents SQL injection (and sometimes makes it easier for a database to optimise queries, so can make it faster too).

Same thing applies on the HTML side - to prevent people injecting HTML/JavaScript you need to use HtmlEditFormat for any unsanitized user input:
code:
Run ID = <cfoutput>#HtmlEditFormat(form.batch)#</cfoutput>


Of course, that matters more for stuff on the actual internet - if this is a local tool then it's a question of if you can trust your work colleagues, but both of them are good habits to get into. :)
EDITED: 21 Apr 2011 00:24 by BOUGHTONP
From: Ken (SHIELDSIT)21 Apr 2011 00:53
To: Peter (BOUGHTONP) 85 of 101

Yes just an internal tool so I'm not really concerned about injections, but you're right. Get in the habit!

 

I have no doubt there are things that need changed. I haven't used CF in about 2 years and even then I wasn't what I would consider much good at it.

From: Ken (SHIELDSIT)21 Apr 2011 13:17
To: Peter (BOUGHTONP) 86 of 101
Any idea why this would work:

code:
WHERE rudID='#form.batch#' AND rudCategory='Produced' AND rudProductID LIKE '%#WoodType#%' AND rudDescrip NOT LIKE '%boards%' AND rudDescrip NOT LIKE '%blocking%'


And this wouldn't?

code:
WHERE rudID='#form.batch#' AND rudCategory='Produced' AND rudProductID LIKE '%#WoodType#%' AND rudDescrip LIKE '%boards%' AND rudDescrip LIKE '%blocking%'


It tells me this:

quote:
Can't cast Complex Object Type Query to String
EDITED: 21 Apr 2011 13:19 by SHIELDSIT
From: Peter (BOUGHTONP)21 Apr 2011 13:42
To: Ken (SHIELDSIT) 87 of 101
It's not the NOTs that are making it not work (and if it was, they would give an SQL error instead).

The error message says you're trying to use a Query variable as if it were a String, and a query can't be implicitly converted (like numbers,booleans,etc can), so it falls over and complains.

Did you do the change in msg:38393.84 and/or anything else?

You've only got two variables shown, form.batch and WoodType - and neither of them should be queries based on the previous code, so either the code has changed, or the data has changed and is causing different behaviour in the code.

Is that definitely the line that the error is pointing to?
If so, are there any other variables inside the cfquery block?
From: Ken (SHIELDSIT)21 Apr 2011 13:47
To: Peter (BOUGHTONP) 88 of 101
No the only thing I changed was removing the NOT.

This works:
code:
<CFQUERY NAME="woodtype" DATASOURCE="isiswood">
	SELECT ID=rudID, Category=rudCategory, Seq=rudSeq, Type=rudType, Product_ID=rudProductID, Description=rudDescrip, 
	PcsPerPkg=rudPcsPerPkg, Tally=rudTally, UOM=rudBaseUnitID, Pieces=rudPieces, Volume=rudVolume, NetVolume=rudNetVolume, Cost=rudCost, AddedCost= rudAddedCost, MktValue=rudMarketValue, Total=rudTotal, NetThick=rudNetThick, 
	NetWidth=rudNetWidth, NetLength=rudNetLength, NetType=rudVolType, LocationID=rudLocationID,rudFIFOVolume,rudForceCost,rudBoomID,prdLengthID=(SELECT prdLengthID 
	FROM ProductMaster WHERE prdID=rudProductID) FROM ProductionDetail WHERE rudID='#form.batch#' AND rudCategory='Produced' AND rudProductID LIKE '%#WoodType#%' AND rudDescrip NOT LIKE '%boards%' AND rudDescrip NOT LIKE '%blocking%'
	ORDER BY Seq;
</cfquery>


This doesn't:
code:
<CFQUERY NAME="bandb" DATASOURCE="isiswood">
	SELECT ID=rudID, Category=rudCategory, Seq=rudSeq, Type=rudType, Product_ID=rudProductID, Description=rudDescrip, 
	PcsPerPkg=rudPcsPerPkg, Tally=rudTally, UOM=rudBaseUnitID, Pieces=rudPieces, Volume=rudVolume, NetVolume=rudNetVolume, Cost=rudCost, AddedCost= rudAddedCost, MktValue=rudMarketValue, Total=rudTotal, NetThick=rudNetThick, 
	NetWidth=rudNetWidth, NetLength=rudNetLength, NetType=rudVolType, LocationID=rudLocationID,rudFIFOVolume,rudForceCost,rudBoomID,prdLengthID=(SELECT prdLengthID 
	FROM ProductMaster WHERE prdID=rudProductID) FROM ProductionDetail WHERE rudID='#form.batch#' AND rudCategory='Produced' AND rudProductID LIKE '%#WoodType#%' AND rudDescrip LIKE '%boards%' OR rudDescrip LIKE '%blocking%'
	ORDER BY Seq;
</cfquery>